summaryrefslogtreecommitdiffstats
path: root/drivers/staging/rtl8723bs/hal
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/rtl8723bs/hal')
-rw-r--r--drivers/staging/rtl8723bs/hal/Hal8723BReg.h438
-rw-r--r--drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c2666
-rw-r--r--drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.h184
-rw-r--r--drivers/staging/rtl8723bs/hal/HalBtc8723b2Ant.c2630
-rw-r--r--drivers/staging/rtl8723bs/hal/HalBtc8723b2Ant.h146
-rw-r--r--drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h426
-rw-r--r--drivers/staging/rtl8723bs/hal/HalHWImg8723B_BB.c570
-rw-r--r--drivers/staging/rtl8723bs/hal/HalHWImg8723B_BB.h40
-rw-r--r--drivers/staging/rtl8723bs/hal/HalHWImg8723B_MAC.c245
-rw-r--r--drivers/staging/rtl8723bs/hal/HalHWImg8723B_MAC.h20
-rw-r--r--drivers/staging/rtl8723bs/hal/HalHWImg8723B_RF.c564
-rw-r--r--drivers/staging/rtl8723bs/hal/HalHWImg8723B_RF.h41
-rw-r--r--drivers/staging/rtl8723bs/hal/HalPhyRf.c273
-rw-r--r--drivers/staging/rtl8723bs/hal/HalPhyRf.h42
-rw-r--r--drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c1822
-rw-r--r--drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.h75
-rw-r--r--drivers/staging/rtl8723bs/hal/HalPwrSeqCmd.c146
-rw-r--r--drivers/staging/rtl8723bs/hal/Mp_Precomp.h23
-rw-r--r--drivers/staging/rtl8723bs/hal/hal_btcoex.c1341
-rw-r--r--drivers/staging/rtl8723bs/hal/hal_com.c1096
-rw-r--r--drivers/staging/rtl8723bs/hal/hal_com_phycfg.c984
-rw-r--r--drivers/staging/rtl8723bs/hal/hal_intf.c439
-rw-r--r--drivers/staging/rtl8723bs/hal/hal_pwr_seq.c130
-rw-r--r--drivers/staging/rtl8723bs/hal/hal_sdio.c106
-rw-r--r--drivers/staging/rtl8723bs/hal/odm.c1197
-rw-r--r--drivers/staging/rtl8723bs/hal/odm.h1175
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_CfoTracking.c211
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_CfoTracking.h39
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_DIG.c825
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_DIG.h169
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_DynamicBBPowerSaving.c81
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_DynamicBBPowerSaving.h31
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_DynamicTxPower.c22
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_DynamicTxPower.h29
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_EdcaTurboCheck.c158
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_EdcaTurboCheck.h23
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_HWConfig.c446
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_HWConfig.h86
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_RegConfig8723B.c179
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_RegConfig8723B.h45
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_RegDefine11N.h162
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_interface.h40
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_precomp.h47
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_reg.h91
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_types.h51
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c980
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_dm.c272
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c3863
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c794
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_rf6052.c168
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_rxdesc.c74
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c479
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c594
-rw-r--r--drivers/staging/rtl8723bs/hal/sdio_halinit.c1301
-rw-r--r--drivers/staging/rtl8723bs/hal/sdio_ops.c1012
55 files changed, 29091 insertions, 0 deletions
diff --git a/drivers/staging/rtl8723bs/hal/Hal8723BReg.h b/drivers/staging/rtl8723bs/hal/Hal8723BReg.h
new file mode 100644
index 000000000..6bf7933cb
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/Hal8723BReg.h
@@ -0,0 +1,438 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*****************************************************************************
+ *Copyright(c) 2009, RealTEK Technology Inc. All Right Reserved.
+ *
+ * Module: __INC_HAL8723BREG_H
+ *
+ *
+ * Note: 1. Define Mac register address and corresponding bit mask map
+ *
+ *
+ * Export: Constants, macro, functions(API), global variables(None).
+ *
+ * Abbrev:
+ *
+ * History:
+ * Data Who Remark
+ *
+ *****************************************************************************/
+#ifndef __INC_HAL8723BREG_H
+#define __INC_HAL8723BREG_H
+
+/* */
+/* */
+/* */
+
+/* */
+/* */
+/* 0x0000h ~ 0x00FFh System Configuration */
+/* */
+/* */
+#define REG_SYS_ISO_CTRL_8723B 0x0000 /* 2 Byte */
+#define REG_SYS_FUNC_EN_8723B 0x0002 /* 2 Byte */
+#define REG_APS_FSMCO_8723B 0x0004 /* 4 Byte */
+#define REG_SYS_CLKR_8723B 0x0008 /* 2 Byte */
+#define REG_9346CR_8723B 0x000A /* 2 Byte */
+#define REG_EE_VPD_8723B 0x000C /* 2 Byte */
+#define REG_AFE_MISC_8723B 0x0010 /* 1 Byte */
+#define REG_SPS0_CTRL_8723B 0x0011 /* 7 Byte */
+#define REG_SPS_OCP_CFG_8723B 0x0018 /* 4 Byte */
+#define REG_RSV_CTRL_8723B 0x001C /* 3 Byte */
+#define REG_RF_CTRL_8723B 0x001F /* 1 Byte */
+#define REG_LPLDO_CTRL_8723B 0x0023 /* 1 Byte */
+#define REG_AFE_XTAL_CTRL_8723B 0x0024 /* 4 Byte */
+#define REG_AFE_PLL_CTRL_8723B 0x0028 /* 4 Byte */
+#define REG_MAC_PLL_CTRL_EXT_8723B 0x002c /* 4 Byte */
+#define REG_EFUSE_CTRL_8723B 0x0030
+#define REG_EFUSE_TEST_8723B 0x0034
+#define REG_PWR_DATA_8723B 0x0038
+#define REG_CAL_TIMER_8723B 0x003C
+#define REG_ACLK_MON_8723B 0x003E
+#define REG_GPIO_MUXCFG_8723B 0x0040
+#define REG_GPIO_IO_SEL_8723B 0x0042
+#define REG_MAC_PINMUX_CFG_8723B 0x0043
+#define REG_GPIO_PIN_CTRL_8723B 0x0044
+#define REG_GPIO_INTM_8723B 0x0048
+#define REG_LEDCFG0_8723B 0x004C
+#define REG_LEDCFG1_8723B 0x004D
+#define REG_LEDCFG2_8723B 0x004E
+#define REG_LEDCFG3_8723B 0x004F
+#define REG_FSIMR_8723B 0x0050
+#define REG_FSISR_8723B 0x0054
+#define REG_HSIMR_8723B 0x0058
+#define REG_HSISR_8723B 0x005c
+#define REG_GPIO_EXT_CTRL 0x0060
+#define REG_MULTI_FUNC_CTRL_8723B 0x0068
+#define REG_GPIO_STATUS_8723B 0x006C
+#define REG_SDIO_CTRL_8723B 0x0070
+#define REG_OPT_CTRL_8723B 0x0074
+#define REG_AFE_XTAL_CTRL_EXT_8723B 0x0078
+#define REG_MCUFWDL_8723B 0x0080
+#define REG_BT_PATCH_STATUS_8723B 0x0088
+#define REG_HIMR0_8723B 0x00B0
+#define REG_HISR0_8723B 0x00B4
+#define REG_HIMR1_8723B 0x00B8
+#define REG_HISR1_8723B 0x00BC
+#define REG_PMC_DBG_CTRL2_8723B 0x00CC
+#define REG_EFUSE_BURN_GNT_8723B 0x00CF
+#define REG_HPON_FSM_8723B 0x00EC
+#define REG_SYS_CFG_8723B 0x00F0
+#define REG_SYS_CFG1_8723B 0x00FC
+#define REG_ROM_VERSION 0x00FD
+
+/* */
+/* */
+/* 0x0100h ~ 0x01FFh MACTOP General Configuration */
+/* */
+/* */
+#define REG_CR_8723B 0x0100
+#define REG_PBP_8723B 0x0104
+#define REG_PKT_BUFF_ACCESS_CTRL_8723B 0x0106
+#define REG_TRXDMA_CTRL_8723B 0x010C
+#define REG_TRXFF_BNDY_8723B 0x0114
+#define REG_TRXFF_STATUS_8723B 0x0118
+#define REG_RXFF_PTR_8723B 0x011C
+#define REG_CPWM_8723B 0x012F
+#define REG_FWIMR_8723B 0x0130
+#define REG_FWISR_8723B 0x0134
+#define REG_FTIMR_8723B 0x0138
+#define REG_PKTBUF_DBG_CTRL_8723B 0x0140
+#define REG_RXPKTBUF_CTRL_8723B 0x0142
+#define REG_PKTBUF_DBG_DATA_L_8723B 0x0144
+#define REG_PKTBUF_DBG_DATA_H_8723B 0x0148
+
+#define REG_TC0_CTRL_8723B 0x0150
+#define REG_TC1_CTRL_8723B 0x0154
+#define REG_TC2_CTRL_8723B 0x0158
+#define REG_TC3_CTRL_8723B 0x015C
+#define REG_TC4_CTRL_8723B 0x0160
+#define REG_TCUNIT_BASE_8723B 0x0164
+#define REG_RSVD3_8723B 0x0168
+#define REG_C2HEVT_MSG_NORMAL_8723B 0x01A0
+#define REG_C2HEVT_CMD_SEQ_88XX 0x01A1
+#define REG_C2HEVT_CMD_CONTENT_88XX 0x01A2
+#define REG_C2HEVT_CMD_LEN_88XX 0x01AE
+#define REG_C2HEVT_CLEAR_8723B 0x01AF
+#define REG_MCUTST_1_8723B 0x01C0
+#define REG_MCUTST_WOWLAN_8723B 0x01C7
+#define REG_FMETHR_8723B 0x01C8
+#define REG_HMETFR_8723B 0x01CC
+#define REG_HMEBOX_0_8723B 0x01D0
+#define REG_HMEBOX_1_8723B 0x01D4
+#define REG_HMEBOX_2_8723B 0x01D8
+#define REG_HMEBOX_3_8723B 0x01DC
+#define REG_LLT_INIT_8723B 0x01E0
+#define REG_HMEBOX_EXT0_8723B 0x01F0
+#define REG_HMEBOX_EXT1_8723B 0x01F4
+#define REG_HMEBOX_EXT2_8723B 0x01F8
+#define REG_HMEBOX_EXT3_8723B 0x01FC
+
+/* */
+/* */
+/* 0x0200h ~ 0x027Fh TXDMA Configuration */
+/* */
+/* */
+#define REG_RQPN_8723B 0x0200
+#define REG_FIFOPAGE_8723B 0x0204
+#define REG_DWBCN0_CTRL_8723B REG_TDECTRL
+#define REG_TXDMA_OFFSET_CHK_8723B 0x020C
+#define REG_TXDMA_STATUS_8723B 0x0210
+#define REG_RQPN_NPQ_8723B 0x0214
+#define REG_DWBCN1_CTRL_8723B 0x0228
+
+/* */
+/* */
+/* 0x0280h ~ 0x02FFh RXDMA Configuration */
+/* */
+/* */
+#define REG_RXDMA_AGG_PG_TH_8723B 0x0280
+#define REG_FW_UPD_RDPTR_8723B 0x0284 /* FW shall update this register before FW write RXPKT_RELEASE_POLL to 1 */
+#define REG_RXDMA_CONTROL_8723B 0x0286 /* Control the RX DMA. */
+#define REG_RXPKT_NUM_8723B 0x0287 /* The number of packets in RXPKTBUF. */
+#define REG_RXDMA_STATUS_8723B 0x0288
+#define REG_RXDMA_PRO_8723B 0x0290
+#define REG_EARLY_MODE_CONTROL_8723B 0x02BC
+#define REG_RSVD5_8723B 0x02F0
+#define REG_RSVD6_8723B 0x02F4
+
+/* */
+/* */
+/* 0x0300h ~ 0x03FFh PCIe */
+/* */
+/* */
+#define REG_PCIE_CTRL_REG_8723B 0x0300
+#define REG_INT_MIG_8723B 0x0304 /* Interrupt Migration */
+#define REG_BCNQ_DESA_8723B 0x0308 /* TX Beacon Descriptor Address */
+#define REG_HQ_DESA_8723B 0x0310 /* TX High Queue Descriptor Address */
+#define REG_MGQ_DESA_8723B 0x0318 /* TX Manage Queue Descriptor Address */
+#define REG_VOQ_DESA_8723B 0x0320 /* TX VO Queue Descriptor Address */
+#define REG_VIQ_DESA_8723B 0x0328 /* TX VI Queue Descriptor Address */
+#define REG_BEQ_DESA_8723B 0x0330 /* TX BE Queue Descriptor Address */
+#define REG_BKQ_DESA_8723B 0x0338 /* TX BK Queue Descriptor Address */
+#define REG_RX_DESA_8723B 0x0340 /* RX Queue Descriptor Address */
+#define REG_DBI_WDATA_8723B 0x0348 /* DBI Write Data */
+#define REG_DBI_RDATA_8723B 0x034C /* DBI Read Data */
+#define REG_DBI_ADDR_8723B 0x0350 /* DBI Address */
+#define REG_DBI_FLAG_8723B 0x0352 /* DBI Read/Write Flag */
+#define REG_MDIO_WDATA_8723B 0x0354 /* MDIO for Write PCIE PHY */
+#define REG_MDIO_RDATA_8723B 0x0356 /* MDIO for Reads PCIE PHY */
+#define REG_MDIO_CTL_8723B 0x0358 /* MDIO for Control */
+#define REG_DBG_SEL_8723B 0x0360 /* Debug Selection Register */
+#define REG_PCIE_HRPWM_8723B 0x0361 /* PCIe RPWM */
+#define REG_PCIE_HCPWM_8723B 0x0363 /* PCIe CPWM */
+#define REG_PCIE_MULTIFET_CTRL_8723B 0x036A /* PCIE Multi-Fethc Control */
+
+/* spec version 11 */
+/* */
+/* */
+/* 0x0400h ~ 0x047Fh Protocol Configuration */
+/* */
+/* */
+#define REG_VOQ_INFORMATION_8723B 0x0400
+#define REG_VIQ_INFORMATION_8723B 0x0404
+#define REG_BEQ_INFORMATION_8723B 0x0408
+#define REG_BKQ_INFORMATION_8723B 0x040C
+#define REG_MGQ_INFORMATION_8723B 0x0410
+#define REG_HGQ_INFORMATION_8723B 0x0414
+#define REG_BCNQ_INFORMATION_8723B 0x0418
+#define REG_TXPKT_EMPTY_8723B 0x041A
+
+#define REG_FWHW_TXQ_CTRL_8723B 0x0420
+#define REG_HWSEQ_CTRL_8723B 0x0423
+#define REG_TXPKTBUF_BCNQ_BDNY_8723B 0x0424
+#define REG_TXPKTBUF_MGQ_BDNY_8723B 0x0425
+#define REG_LIFECTRL_CTRL_8723B 0x0426
+#define REG_MULTI_BCNQ_OFFSET_8723B 0x0427
+#define REG_SPEC_SIFS_8723B 0x0428
+#define REG_RL_8723B 0x042A
+#define REG_TXBF_CTRL_8723B 0x042C
+#define REG_DARFRC_8723B 0x0430
+#define REG_RARFRC_8723B 0x0438
+#define REG_RRSR_8723B 0x0440
+#define REG_ARFR0_8723B 0x0444
+#define REG_ARFR1_8723B 0x044C
+#define REG_CCK_CHECK_8723B 0x0454
+#define REG_AMPDU_MAX_TIME_8723B 0x0456
+#define REG_TXPKTBUF_BCNQ_BDNY1_8723B 0x0457
+
+#define REG_AMPDU_MAX_LENGTH_8723B 0x0458
+#define REG_TXPKTBUF_WMAC_LBK_BF_HD_8723B 0x045D
+#define REG_NDPA_OPT_CTRL_8723B 0x045F
+#define REG_FAST_EDCA_CTRL_8723B 0x0460
+#define REG_RD_RESP_PKT_TH_8723B 0x0463
+#define REG_DATA_SC_8723B 0x0483
+#define REG_TXRPT_START_OFFSET 0x04AC
+#define REG_POWER_STAGE1_8723B 0x04B4
+#define REG_POWER_STAGE2_8723B 0x04B8
+#define REG_AMPDU_BURST_MODE_8723B 0x04BC
+#define REG_PKT_VO_VI_LIFE_TIME_8723B 0x04C0
+#define REG_PKT_BE_BK_LIFE_TIME_8723B 0x04C2
+#define REG_STBC_SETTING_8723B 0x04C4
+#define REG_HT_SINGLE_AMPDU_8723B 0x04C7
+#define REG_PROT_MODE_CTRL_8723B 0x04C8
+#define REG_MAX_AGGR_NUM_8723B 0x04CA
+#define REG_RTS_MAX_AGGR_NUM_8723B 0x04CB
+#define REG_BAR_MODE_CTRL_8723B 0x04CC
+#define REG_RA_TRY_RATE_AGG_LMT_8723B 0x04CF
+#define REG_MACID_PKT_DROP0_8723B 0x04D0
+#define REG_MACID_PKT_SLEEP_8723B 0x04D4
+
+/* */
+/* */
+/* 0x0500h ~ 0x05FFh EDCA Configuration */
+/* */
+/* */
+#define REG_EDCA_VO_PARAM_8723B 0x0500
+#define REG_EDCA_VI_PARAM_8723B 0x0504
+#define REG_EDCA_BE_PARAM_8723B 0x0508
+#define REG_EDCA_BK_PARAM_8723B 0x050C
+#define REG_BCNTCFG_8723B 0x0510
+#define REG_PIFS_8723B 0x0512
+#define REG_RDG_PIFS_8723B 0x0513
+#define REG_SIFS_CTX_8723B 0x0514
+#define REG_SIFS_TRX_8723B 0x0516
+#define REG_AGGR_BREAK_TIME_8723B 0x051A
+#define REG_SLOT_8723B 0x051B
+#define REG_TX_PTCL_CTRL_8723B 0x0520
+#define REG_TXPAUSE_8723B 0x0522
+#define REG_DIS_TXREQ_CLR_8723B 0x0523
+#define REG_RD_CTRL_8723B 0x0524
+/* */
+/* Format for offset 540h-542h: */
+/* [3:0]: TBTT prohibit setup in unit of 32us. The time for HW getting beacon content before TBTT. */
+/* [7:4]: Reserved. */
+/* [19:8]: TBTT prohibit hold in unit of 32us. The time for HW holding to send the beacon packet. */
+/* [23:20]: Reserved */
+/* Description: */
+/* | */
+/* |<--Setup--|--Hold------------>| */
+/* --------------|---------------------- */
+/* | */
+/* TBTT */
+/* Note: We cannot update beacon content to HW or send any AC packets during the time between Setup and Hold. */
+/* Described by Designer Tim and Bruce, 2011-01-14. */
+/* */
+#define REG_TBTT_PROHIBIT_8723B 0x0540
+#define REG_RD_NAV_NXT_8723B 0x0544
+#define REG_NAV_PROT_LEN_8723B 0x0546
+#define REG_BCN_CTRL_8723B 0x0550
+#define REG_BCN_CTRL_1_8723B 0x0551
+#define REG_MBID_NUM_8723B 0x0552
+#define REG_DUAL_TSF_RST_8723B 0x0553
+#define REG_BCN_INTERVAL_8723B 0x0554
+#define REG_DRVERLYINT_8723B 0x0558
+#define REG_BCNDMATIM_8723B 0x0559
+#define REG_ATIMWND_8723B 0x055A
+#define REG_USTIME_TSF_8723B 0x055C
+#define REG_BCN_MAX_ERR_8723B 0x055D
+#define REG_RXTSF_OFFSET_CCK_8723B 0x055E
+#define REG_RXTSF_OFFSET_OFDM_8723B 0x055F
+#define REG_TSFTR_8723B 0x0560
+#define REG_CTWND_8723B 0x0572
+#define REG_SECONDARY_CCA_CTRL_8723B 0x0577
+#define REG_PSTIMER_8723B 0x0580
+#define REG_TIMER0_8723B 0x0584
+#define REG_TIMER1_8723B 0x0588
+#define REG_ACMHWCTRL_8723B 0x05C0
+#define REG_SCH_TXCMD_8723B 0x05F8
+
+/* 0x0600h ~ 0x07FFh WMAC Configuration */
+#define REG_MAC_CR_8723B 0x0600
+#define REG_TCR_8723B 0x0604
+#define REG_RCR_8723B 0x0608
+#define REG_RX_PKT_LIMIT_8723B 0x060C
+#define REG_RX_DLK_TIME_8723B 0x060D
+#define REG_RX_DRVINFO_SZ_8723B 0x060F
+
+#define REG_MACID_8723B 0x0610
+#define REG_BSSID_8723B 0x0618
+#define REG_MAR_8723B 0x0620
+#define REG_MBIDCAMCFG_8723B 0x0628
+
+#define REG_USTIME_EDCA_8723B 0x0638
+#define REG_MAC_SPEC_SIFS_8723B 0x063A
+#define REG_RESP_SIFP_CCK_8723B 0x063C
+#define REG_RESP_SIFS_OFDM_8723B 0x063E
+#define REG_ACKTO_8723B 0x0640
+#define REG_CTS2TO_8723B 0x0641
+#define REG_EIFS_8723B 0x0642
+
+#define REG_NAV_UPPER_8723B 0x0652 /* unit of 128 */
+#define REG_TRXPTCL_CTL_8723B 0x0668
+
+/* Security */
+#define REG_CAMCMD_8723B 0x0670
+#define REG_CAMWRITE_8723B 0x0674
+#define REG_CAMREAD_8723B 0x0678
+#define REG_CAMDBG_8723B 0x067C
+#define REG_SECCFG_8723B 0x0680
+
+/* Power */
+#define REG_WOW_CTRL_8723B 0x0690
+#define REG_PS_RX_INFO_8723B 0x0692
+#define REG_UAPSD_TID_8723B 0x0693
+#define REG_WKFMCAM_CMD_8723B 0x0698
+#define REG_WKFMCAM_NUM_8723B 0x0698
+#define REG_WKFMCAM_RWD_8723B 0x069C
+#define REG_RXFLTMAP0_8723B 0x06A0
+#define REG_RXFLTMAP1_8723B 0x06A2
+#define REG_RXFLTMAP2_8723B 0x06A4
+#define REG_BCN_PSR_RPT_8723B 0x06A8
+#define REG_BT_COEX_TABLE_8723B 0x06C0
+#define REG_BFMER0_INFO_8723B 0x06E4
+#define REG_BFMER1_INFO_8723B 0x06EC
+#define REG_CSI_RPT_PARAM_BW20_8723B 0x06F4
+#define REG_CSI_RPT_PARAM_BW40_8723B 0x06F8
+#define REG_CSI_RPT_PARAM_BW80_8723B 0x06FC
+
+/* Hardware Port 2 */
+#define REG_MACID1_8723B 0x0700
+#define REG_BSSID1_8723B 0x0708
+#define REG_BFMEE_SEL_8723B 0x0714
+#define REG_SND_PTCL_CTRL_8723B 0x0718
+
+/* Redifine 8192C register definition for compatibility */
+
+/* TODO: use these definition when using REG_xxx naming rule. */
+/* NOTE: DO NOT Remove these definition. Use later. */
+#define EFUSE_CTRL_8723B REG_EFUSE_CTRL_8723B /* E-Fuse Control. */
+#define EFUSE_TEST_8723B REG_EFUSE_TEST_8723B /* E-Fuse Test. */
+#define MSR_8723B (REG_CR_8723B + 2) /* Media Status register */
+#define ISR_8723B REG_HISR0_8723B
+#define TSFR_8723B REG_TSFTR_8723B /* Timing Sync Function Timer Register. */
+
+#define PBP_8723B REG_PBP_8723B
+
+/* Redifine MACID register, to compatible prior ICs. */
+#define IDR0_8723B REG_MACID_8723B /* MAC ID Register, Offset 0x0050-0x0053 */
+#define IDR4_8723B (REG_MACID_8723B + 4) /* MAC ID Register, Offset 0x0054-0x0055 */
+
+/* 9. Security Control Registers (Offset:) */
+#define RWCAM_8723B REG_CAMCMD_8723B /* IN 8190 Data Sheet is called CAMcmd */
+#define WCAMI_8723B REG_CAMWRITE_8723B /* Software write CAM input content */
+#define RCAMO_8723B REG_CAMREAD_8723B /* Software read/write CAM config */
+#define CAMDBG_8723B REG_CAMDBG_8723B
+#define SECR_8723B REG_SECCFG_8723B /* Security Configuration Register */
+
+/* 8195 IMR/ISR bits (offset 0xB0, 8bits) */
+#define IMR_DISABLED_8723B 0
+/* IMR DW0(0x00B0-00B3) Bit 0-31 */
+#define IMR_TIMER2_8723B BIT31 /* Timeout interrupt 2 */
+#define IMR_TIMER1_8723B BIT30 /* Timeout interrupt 1 */
+#define IMR_PSTIMEOUT_8723B BIT29 /* Power Save Time Out Interrupt */
+#define IMR_GTINT4_8723B BIT28 /* When GTIMER4 expires, this bit is set to 1 */
+#define IMR_GTINT3_8723B BIT27 /* When GTIMER3 expires, this bit is set to 1 */
+#define IMR_TXBCN0ERR_8723B BIT26 /* Transmit Beacon0 Error */
+#define IMR_TXBCN0OK_8723B BIT25 /* Transmit Beacon0 OK */
+#define IMR_TSF_BIT32_TOGGLE_8723B BIT24 /* TSF Timer BIT32 toggle indication interrupt */
+#define IMR_BCNDMAINT0_8723B BIT20 /* Beacon DMA Interrupt 0 */
+#define IMR_BCNDERR0_8723B BIT16 /* Beacon Queue DMA OK0 */
+#define IMR_HSISR_IND_ON_INT_8723B BIT15 /* HSISR Indicator (HSIMR & HSISR is true, this bit is set to 1) */
+#define IMR_BCNDMAINT_E_8723B BIT14 /* Beacon DMA Interrupt Extension for Win7 */
+#define IMR_ATIMEND_8723B BIT12 /* CTWidnow End or ATIM Window End */
+#define IMR_C2HCMD_8723B BIT10 /* CPU to Host Command INT Status, Write 1 clear */
+#define IMR_CPWM2_8723B BIT9 /* CPU power Mode exchange INT Status, Write 1 clear */
+#define IMR_CPWM_8723B BIT8 /* CPU power Mode exchange INT Status, Write 1 clear */
+#define IMR_HIGHDOK_8723B BIT7 /* High Queue DMA OK */
+#define IMR_MGNTDOK_8723B BIT6 /* Management Queue DMA OK */
+#define IMR_BKDOK_8723B BIT5 /* AC_BK DMA OK */
+#define IMR_BEDOK_8723B BIT4 /* AC_BE DMA OK */
+#define IMR_VIDOK_8723B BIT3 /* AC_VI DMA OK */
+#define IMR_VODOK_8723B BIT2 /* AC_VO DMA OK */
+#define IMR_RDU_8723B BIT1 /* Rx Descriptor Unavailable */
+#define IMR_ROK_8723B BIT0 /* Receive DMA OK */
+
+/* IMR DW1(0x00B4-00B7) Bit 0-31 */
+#define IMR_BCNDMAINT7_8723B BIT27 /* Beacon DMA Interrupt 7 */
+#define IMR_BCNDMAINT6_8723B BIT26 /* Beacon DMA Interrupt 6 */
+#define IMR_BCNDMAINT5_8723B BIT25 /* Beacon DMA Interrupt 5 */
+#define IMR_BCNDMAINT4_8723B BIT24 /* Beacon DMA Interrupt 4 */
+#define IMR_BCNDMAINT3_8723B BIT23 /* Beacon DMA Interrupt 3 */
+#define IMR_BCNDMAINT2_8723B BIT22 /* Beacon DMA Interrupt 2 */
+#define IMR_BCNDMAINT1_8723B BIT21 /* Beacon DMA Interrupt 1 */
+#define IMR_BCNDOK7_8723B BIT20 /* Beacon Queue DMA OK Interrupt 7 */
+#define IMR_BCNDOK6_8723B BIT19 /* Beacon Queue DMA OK Interrupt 6 */
+#define IMR_BCNDOK5_8723B BIT18 /* Beacon Queue DMA OK Interrupt 5 */
+#define IMR_BCNDOK4_8723B BIT17 /* Beacon Queue DMA OK Interrupt 4 */
+#define IMR_BCNDOK3_8723B BIT16 /* Beacon Queue DMA OK Interrupt 3 */
+#define IMR_BCNDOK2_8723B BIT15 /* Beacon Queue DMA OK Interrupt 2 */
+#define IMR_BCNDOK1_8723B BIT14 /* Beacon Queue DMA OK Interrupt 1 */
+#define IMR_ATIMEND_E_8723B BIT13 /* ATIM Window End Extension for Win7 */
+#define IMR_TXERR_8723B BIT11 /* Tx Error Flag Interrupt Status, write 1 clear. */
+#define IMR_RXERR_8723B BIT10 /* Rx Error Flag INT Status, Write 1 clear */
+#define IMR_TXFOVW_8723B BIT9 /* Transmit FIFO Overflow */
+#define IMR_RXFOVW_8723B BIT8 /* Receive FIFO Overflow */
+
+/* 2 ACMHWCTRL 0x05C0 */
+#define ACMHW_HWEN_8723B BIT(0)
+#define ACMHW_VOQEN_8723B BIT(1)
+#define ACMHW_VIQEN_8723B BIT(2)
+#define ACMHW_BEQEN_8723B BIT(3)
+#define ACMHW_VOQSTATUS_8723B BIT(5)
+#define ACMHW_VIQSTATUS_8723B BIT(6)
+#define ACMHW_BEQSTATUS_8723B BIT(7)
+
+/* 8195 (RCR) Receive Configuration Register (Offset 0x608, 32 bits) */
+#define RCR_TCPOFLD_EN BIT25 /* Enable TCP checksum offload */
+
+#endif /* #ifndef __INC_HAL8723BREG_H */
diff --git a/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c b/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c
new file mode 100644
index 000000000..b3d7f50fa
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c
@@ -0,0 +1,2666 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include "Mp_Precomp.h"
+
+/* Global variables, these are static variables */
+static struct coex_dm_8723b_1ant GLCoexDm8723b1Ant;
+static struct coex_dm_8723b_1ant *pCoexDm = &GLCoexDm8723b1Ant;
+static struct coex_sta_8723b_1ant GLCoexSta8723b1Ant;
+static struct coex_sta_8723b_1ant *pCoexSta = &GLCoexSta8723b1Ant;
+
+/* local function proto type if needed */
+/* local function start with halbtc8723b1ant_ */
+static u8 halbtc8723b1ant_BtRssiState(
+ u8 levelNum, u8 rssiThresh, u8 rssiThresh1
+)
+{
+ s32 btRssi = 0;
+ u8 btRssiState = pCoexSta->preBtRssiState;
+
+ btRssi = pCoexSta->btRssi;
+
+ if (levelNum == 2) {
+ if (
+ (pCoexSta->preBtRssiState == BTC_RSSI_STATE_LOW) ||
+ (pCoexSta->preBtRssiState == BTC_RSSI_STATE_STAY_LOW)
+ ) {
+ if (btRssi >= (rssiThresh + BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT))
+
+ btRssiState = BTC_RSSI_STATE_HIGH;
+ else
+ btRssiState = BTC_RSSI_STATE_STAY_LOW;
+ } else {
+ if (btRssi < rssiThresh)
+ btRssiState = BTC_RSSI_STATE_LOW;
+ else
+ btRssiState = BTC_RSSI_STATE_STAY_HIGH;
+ }
+ } else if (levelNum == 3) {
+ if (rssiThresh > rssiThresh1)
+ return pCoexSta->preBtRssiState;
+
+ if (
+ (pCoexSta->preBtRssiState == BTC_RSSI_STATE_LOW) ||
+ (pCoexSta->preBtRssiState == BTC_RSSI_STATE_STAY_LOW)
+ ) {
+ if (btRssi >= (rssiThresh + BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT))
+ btRssiState = BTC_RSSI_STATE_MEDIUM;
+ else
+ btRssiState = BTC_RSSI_STATE_STAY_LOW;
+ } else if (
+ (pCoexSta->preBtRssiState == BTC_RSSI_STATE_MEDIUM) ||
+ (pCoexSta->preBtRssiState == BTC_RSSI_STATE_STAY_MEDIUM)
+ ) {
+ if (btRssi >= (rssiThresh1 + BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT))
+ btRssiState = BTC_RSSI_STATE_HIGH;
+ else if (btRssi < rssiThresh)
+ btRssiState = BTC_RSSI_STATE_LOW;
+ else
+ btRssiState = BTC_RSSI_STATE_STAY_MEDIUM;
+ } else {
+ if (btRssi < rssiThresh1)
+ btRssiState = BTC_RSSI_STATE_MEDIUM;
+ else
+ btRssiState = BTC_RSSI_STATE_STAY_HIGH;
+ }
+ }
+
+ pCoexSta->preBtRssiState = btRssiState;
+
+ return btRssiState;
+}
+
+static void halbtc8723b1ant_UpdateRaMask(
+ struct btc_coexist *pBtCoexist, bool bForceExec, u32 disRateMask
+)
+{
+ pCoexDm->curRaMask = disRateMask;
+
+ if (bForceExec || (pCoexDm->preRaMask != pCoexDm->curRaMask))
+ pBtCoexist->fBtcSet(
+ pBtCoexist,
+ BTC_SET_ACT_UPDATE_RAMASK,
+ &pCoexDm->curRaMask
+ );
+ pCoexDm->preRaMask = pCoexDm->curRaMask;
+}
+
+static void halbtc8723b1ant_AutoRateFallbackRetry(
+ struct btc_coexist *pBtCoexist, bool bForceExec, u8 type
+)
+{
+ bool bWifiUnderBMode = false;
+
+ pCoexDm->curArfrType = type;
+
+ if (bForceExec || (pCoexDm->preArfrType != pCoexDm->curArfrType)) {
+ switch (pCoexDm->curArfrType) {
+ case 0: /* normal mode */
+ pBtCoexist->fBtcWrite4Byte(
+ pBtCoexist, 0x430, pCoexDm->backupArfrCnt1
+ );
+ pBtCoexist->fBtcWrite4Byte(
+ pBtCoexist, 0x434, pCoexDm->backupArfrCnt2
+ );
+ break;
+ case 1:
+ pBtCoexist->fBtcGet(
+ pBtCoexist, BTC_GET_BL_WIFI_UNDER_B_MODE, &bWifiUnderBMode
+ );
+ if (bWifiUnderBMode) {
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x430, 0x0);
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x434, 0x01010101);
+ } else {
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x430, 0x0);
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x434, 0x04030201);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ pCoexDm->preArfrType = pCoexDm->curArfrType;
+}
+
+static void halbtc8723b1ant_RetryLimit(
+ struct btc_coexist *pBtCoexist, bool bForceExec, u8 type
+)
+{
+ pCoexDm->curRetryLimitType = type;
+
+ if (
+ bForceExec ||
+ (pCoexDm->preRetryLimitType != pCoexDm->curRetryLimitType)
+ ) {
+ switch (pCoexDm->curRetryLimitType) {
+ case 0: /* normal mode */
+ pBtCoexist->fBtcWrite2Byte(
+ pBtCoexist, 0x42a, pCoexDm->backupRetryLimit
+ );
+ break;
+ case 1: /* retry limit =8 */
+ pBtCoexist->fBtcWrite2Byte(pBtCoexist, 0x42a, 0x0808);
+ break;
+ default:
+ break;
+ }
+ }
+
+ pCoexDm->preRetryLimitType = pCoexDm->curRetryLimitType;
+}
+
+static void halbtc8723b1ant_AmpduMaxTime(
+ struct btc_coexist *pBtCoexist, bool bForceExec, u8 type
+)
+{
+ pCoexDm->curAmpduTimeType = type;
+
+ if (
+ bForceExec || (pCoexDm->preAmpduTimeType != pCoexDm->curAmpduTimeType)
+ ) {
+ switch (pCoexDm->curAmpduTimeType) {
+ case 0: /* normal mode */
+ pBtCoexist->fBtcWrite1Byte(
+ pBtCoexist, 0x456, pCoexDm->backupAmpduMaxTime
+ );
+ break;
+ case 1: /* AMPDU timw = 0x38 * 32us */
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x456, 0x38);
+ break;
+ default:
+ break;
+ }
+ }
+
+ pCoexDm->preAmpduTimeType = pCoexDm->curAmpduTimeType;
+}
+
+static void halbtc8723b1ant_LimitedTx(
+ struct btc_coexist *pBtCoexist,
+ bool bForceExec,
+ u8 raMaskType,
+ u8 arfrType,
+ u8 retryLimitType,
+ u8 ampduTimeType
+)
+{
+ switch (raMaskType) {
+ case 0: /* normal mode */
+ halbtc8723b1ant_UpdateRaMask(pBtCoexist, bForceExec, 0x0);
+ break;
+ case 1: /* disable cck 1/2 */
+ halbtc8723b1ant_UpdateRaMask(pBtCoexist, bForceExec, 0x00000003);
+ break;
+ case 2: /* disable cck 1/2/5.5, ofdm 6/9/12/18/24, mcs 0/1/2/3/4 */
+ halbtc8723b1ant_UpdateRaMask(pBtCoexist, bForceExec, 0x0001f1f7);
+ break;
+ default:
+ break;
+ }
+
+ halbtc8723b1ant_AutoRateFallbackRetry(pBtCoexist, bForceExec, arfrType);
+ halbtc8723b1ant_RetryLimit(pBtCoexist, bForceExec, retryLimitType);
+ halbtc8723b1ant_AmpduMaxTime(pBtCoexist, bForceExec, ampduTimeType);
+}
+
+static void halbtc8723b1ant_LimitedRx(
+ struct btc_coexist *pBtCoexist,
+ bool bForceExec,
+ bool bRejApAggPkt,
+ bool bBtCtrlAggBufSize,
+ u8 aggBufSize
+)
+{
+ bool bRejectRxAgg = bRejApAggPkt;
+ bool bBtCtrlRxAggSize = bBtCtrlAggBufSize;
+ u8 rxAggSize = aggBufSize;
+
+ /* */
+ /* Rx Aggregation related setting */
+ /* */
+ pBtCoexist->fBtcSet(
+ pBtCoexist, BTC_SET_BL_TO_REJ_AP_AGG_PKT, &bRejectRxAgg
+ );
+ /* decide BT control aggregation buf size or not */
+ pBtCoexist->fBtcSet(
+ pBtCoexist, BTC_SET_BL_BT_CTRL_AGG_SIZE, &bBtCtrlRxAggSize
+ );
+ /* aggregation buf size, only work when BT control Rx aggregation size. */
+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_U1_AGG_BUF_SIZE, &rxAggSize);
+ /* real update aggregation setting */
+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_ACT_AGGREGATE_CTRL, NULL);
+
+
+}
+
+static void halbtc8723b1ant_QueryBtInfo(struct btc_coexist *pBtCoexist)
+{
+ u8 H2C_Parameter[1] = {0};
+
+ pCoexSta->bC2hBtInfoReqSent = true;
+
+ H2C_Parameter[0] |= BIT0; /* trigger */
+
+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x61, 1, H2C_Parameter);
+}
+
+static void halbtc8723b1ant_MonitorBtCtr(struct btc_coexist *pBtCoexist)
+{
+ u32 regHPTxRx, regLPTxRx, u4Tmp;
+ u32 regHPTx = 0, regHPRx = 0, regLPTx = 0, regLPRx = 0;
+ static u8 NumOfBtCounterChk;
+
+ /* to avoid 0x76e[3] = 1 (WLAN_Act control by PTA) during IPS */
+ /* if (! (pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x76e) & 0x8)) */
+
+ if (pCoexSta->bUnderIps) {
+ pCoexSta->highPriorityTx = 65535;
+ pCoexSta->highPriorityRx = 65535;
+ pCoexSta->lowPriorityTx = 65535;
+ pCoexSta->lowPriorityRx = 65535;
+ return;
+ }
+
+ regHPTxRx = 0x770;
+ regLPTxRx = 0x774;
+
+ u4Tmp = pBtCoexist->fBtcRead4Byte(pBtCoexist, regHPTxRx);
+ regHPTx = u4Tmp & bMaskLWord;
+ regHPRx = (u4Tmp & bMaskHWord) >> 16;
+
+ u4Tmp = pBtCoexist->fBtcRead4Byte(pBtCoexist, regLPTxRx);
+ regLPTx = u4Tmp & bMaskLWord;
+ regLPRx = (u4Tmp & bMaskHWord) >> 16;
+
+ pCoexSta->highPriorityTx = regHPTx;
+ pCoexSta->highPriorityRx = regHPRx;
+ pCoexSta->lowPriorityTx = regLPTx;
+ pCoexSta->lowPriorityRx = regLPRx;
+
+ if ((pCoexSta->lowPriorityTx >= 1050) && (!pCoexSta->bC2hBtInquiryPage))
+ pCoexSta->popEventCnt++;
+
+ /* reset counter */
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x76e, 0xc);
+
+ if ((regHPTx == 0) && (regHPRx == 0) && (regLPTx == 0) && (regLPRx == 0)) {
+ NumOfBtCounterChk++;
+ if (NumOfBtCounterChk >= 3) {
+ halbtc8723b1ant_QueryBtInfo(pBtCoexist);
+ NumOfBtCounterChk = 0;
+ }
+ }
+}
+
+
+static void halbtc8723b1ant_MonitorWiFiCtr(struct btc_coexist *pBtCoexist)
+{
+ s32 wifiRssi = 0;
+ bool bWifiBusy = false, bWifiUnderBMode = false;
+ static u8 nCCKLockCounter;
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_BUSY, &bWifiBusy);
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_S4_WIFI_RSSI, &wifiRssi);
+ pBtCoexist->fBtcGet(
+ pBtCoexist, BTC_GET_BL_WIFI_UNDER_B_MODE, &bWifiUnderBMode
+ );
+
+ if (pCoexSta->bUnderIps) {
+ pCoexSta->nCRCOK_CCK = 0;
+ pCoexSta->nCRCOK_11g = 0;
+ pCoexSta->nCRCOK_11n = 0;
+ pCoexSta->nCRCOK_11nAgg = 0;
+
+ pCoexSta->nCRCErr_CCK = 0;
+ pCoexSta->nCRCErr_11g = 0;
+ pCoexSta->nCRCErr_11n = 0;
+ pCoexSta->nCRCErr_11nAgg = 0;
+ } else {
+ pCoexSta->nCRCOK_CCK = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0xf88);
+ pCoexSta->nCRCOK_11g = pBtCoexist->fBtcRead2Byte(pBtCoexist, 0xf94);
+ pCoexSta->nCRCOK_11n = pBtCoexist->fBtcRead2Byte(pBtCoexist, 0xf90);
+ pCoexSta->nCRCOK_11nAgg = pBtCoexist->fBtcRead2Byte(pBtCoexist, 0xfb8);
+
+ pCoexSta->nCRCErr_CCK = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0xf84);
+ pCoexSta->nCRCErr_11g = pBtCoexist->fBtcRead2Byte(pBtCoexist, 0xf96);
+ pCoexSta->nCRCErr_11n = pBtCoexist->fBtcRead2Byte(pBtCoexist, 0xf92);
+ pCoexSta->nCRCErr_11nAgg = pBtCoexist->fBtcRead2Byte(pBtCoexist, 0xfba);
+ }
+
+
+ /* reset counter */
+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0xf16, 0x1, 0x1);
+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0xf16, 0x1, 0x0);
+
+ if (bWifiBusy && (wifiRssi >= 30) && !bWifiUnderBMode) {
+ if (
+ (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_BUSY) ||
+ (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY) ||
+ (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_SCO_BUSY)
+ ) {
+ if (
+ pCoexSta->nCRCOK_CCK > (
+ pCoexSta->nCRCOK_11g +
+ pCoexSta->nCRCOK_11n +
+ pCoexSta->nCRCOK_11nAgg
+ )
+ ) {
+ if (nCCKLockCounter < 5)
+ nCCKLockCounter++;
+ } else {
+ if (nCCKLockCounter > 0)
+ nCCKLockCounter--;
+ }
+
+ } else {
+ if (nCCKLockCounter > 0)
+ nCCKLockCounter--;
+ }
+ } else {
+ if (nCCKLockCounter > 0)
+ nCCKLockCounter--;
+ }
+
+ if (!pCoexSta->bPreCCKLock) {
+
+ if (nCCKLockCounter >= 5)
+ pCoexSta->bCCKLock = true;
+ else
+ pCoexSta->bCCKLock = false;
+ } else {
+ if (nCCKLockCounter == 0)
+ pCoexSta->bCCKLock = false;
+ else
+ pCoexSta->bCCKLock = true;
+ }
+
+ pCoexSta->bPreCCKLock = pCoexSta->bCCKLock;
+
+
+}
+
+static bool halbtc8723b1ant_IsWifiStatusChanged(struct btc_coexist *pBtCoexist)
+{
+ static bool bPreWifiBusy, bPreUnder4way, bPreBtHsOn;
+ bool bWifiBusy = false, bUnder4way = false, bBtHsOn = false;
+ bool bWifiConnected = false;
+
+ pBtCoexist->fBtcGet(
+ pBtCoexist, BTC_GET_BL_WIFI_CONNECTED, &bWifiConnected
+ );
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_BUSY, &bWifiBusy);
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn);
+ pBtCoexist->fBtcGet(
+ pBtCoexist, BTC_GET_BL_WIFI_4_WAY_PROGRESS, &bUnder4way
+ );
+
+ if (bWifiConnected) {
+ if (bWifiBusy != bPreWifiBusy) {
+ bPreWifiBusy = bWifiBusy;
+ return true;
+ }
+
+ if (bUnder4way != bPreUnder4way) {
+ bPreUnder4way = bUnder4way;
+ return true;
+ }
+
+ if (bBtHsOn != bPreBtHsOn) {
+ bPreBtHsOn = bBtHsOn;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static void halbtc8723b1ant_UpdateBtLinkInfo(struct btc_coexist *pBtCoexist)
+{
+ struct btc_bt_link_info *pBtLinkInfo = &pBtCoexist->btLinkInfo;
+ bool bBtHsOn = false;
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn);
+
+ pBtLinkInfo->bBtLinkExist = pCoexSta->bBtLinkExist;
+ pBtLinkInfo->bScoExist = pCoexSta->bScoExist;
+ pBtLinkInfo->bA2dpExist = pCoexSta->bA2dpExist;
+ pBtLinkInfo->bPanExist = pCoexSta->bPanExist;
+ pBtLinkInfo->bHidExist = pCoexSta->bHidExist;
+
+ /* work around for HS mode. */
+ if (bBtHsOn) {
+ pBtLinkInfo->bPanExist = true;
+ pBtLinkInfo->bBtLinkExist = true;
+ }
+
+ /* check if Sco only */
+ if (
+ pBtLinkInfo->bScoExist &&
+ !pBtLinkInfo->bA2dpExist &&
+ !pBtLinkInfo->bPanExist &&
+ !pBtLinkInfo->bHidExist
+ )
+ pBtLinkInfo->bScoOnly = true;
+ else
+ pBtLinkInfo->bScoOnly = false;
+
+ /* check if A2dp only */
+ if (
+ !pBtLinkInfo->bScoExist &&
+ pBtLinkInfo->bA2dpExist &&
+ !pBtLinkInfo->bPanExist &&
+ !pBtLinkInfo->bHidExist
+ )
+ pBtLinkInfo->bA2dpOnly = true;
+ else
+ pBtLinkInfo->bA2dpOnly = false;
+
+ /* check if Pan only */
+ if (
+ !pBtLinkInfo->bScoExist &&
+ !pBtLinkInfo->bA2dpExist &&
+ pBtLinkInfo->bPanExist &&
+ !pBtLinkInfo->bHidExist
+ )
+ pBtLinkInfo->bPanOnly = true;
+ else
+ pBtLinkInfo->bPanOnly = false;
+
+ /* check if Hid only */
+ if (
+ !pBtLinkInfo->bScoExist &&
+ !pBtLinkInfo->bA2dpExist &&
+ !pBtLinkInfo->bPanExist &&
+ pBtLinkInfo->bHidExist
+ )
+ pBtLinkInfo->bHidOnly = true;
+ else
+ pBtLinkInfo->bHidOnly = false;
+}
+
+static u8 halbtc8723b1ant_ActionAlgorithm(struct btc_coexist *pBtCoexist)
+{
+ struct btc_bt_link_info *pBtLinkInfo = &pBtCoexist->btLinkInfo;
+ bool bBtHsOn = false;
+ u8 algorithm = BT_8723B_1ANT_COEX_ALGO_UNDEFINED;
+ u8 numOfDiffProfile = 0;
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn);
+
+ if (!pBtLinkInfo->bBtLinkExist)
+ return algorithm;
+
+ if (pBtLinkInfo->bScoExist)
+ numOfDiffProfile++;
+ if (pBtLinkInfo->bHidExist)
+ numOfDiffProfile++;
+ if (pBtLinkInfo->bPanExist)
+ numOfDiffProfile++;
+ if (pBtLinkInfo->bA2dpExist)
+ numOfDiffProfile++;
+
+ if (numOfDiffProfile == 1) {
+ if (pBtLinkInfo->bScoExist) {
+ algorithm = BT_8723B_1ANT_COEX_ALGO_SCO;
+ } else {
+ if (pBtLinkInfo->bHidExist) {
+ algorithm = BT_8723B_1ANT_COEX_ALGO_HID;
+ } else if (pBtLinkInfo->bA2dpExist) {
+ algorithm = BT_8723B_1ANT_COEX_ALGO_A2DP;
+ } else if (pBtLinkInfo->bPanExist) {
+ if (bBtHsOn)
+ algorithm = BT_8723B_1ANT_COEX_ALGO_PANHS;
+ else
+ algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR;
+ }
+ }
+ } else if (numOfDiffProfile == 2) {
+ if (pBtLinkInfo->bScoExist) {
+ if (pBtLinkInfo->bHidExist) {
+ algorithm = BT_8723B_1ANT_COEX_ALGO_HID;
+ } else if (pBtLinkInfo->bA2dpExist) {
+ algorithm = BT_8723B_1ANT_COEX_ALGO_SCO;
+ } else if (pBtLinkInfo->bPanExist) {
+ if (bBtHsOn)
+ algorithm = BT_8723B_1ANT_COEX_ALGO_SCO;
+ else
+ algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR_HID;
+ }
+ } else {
+ if (pBtLinkInfo->bHidExist && pBtLinkInfo->bA2dpExist) {
+ algorithm = BT_8723B_1ANT_COEX_ALGO_HID_A2DP;
+ } else if (pBtLinkInfo->bHidExist && pBtLinkInfo->bPanExist) {
+ if (bBtHsOn)
+ algorithm = BT_8723B_1ANT_COEX_ALGO_HID_A2DP;
+ else
+ algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR_HID;
+ } else if (pBtLinkInfo->bPanExist && pBtLinkInfo->bA2dpExist) {
+ if (bBtHsOn)
+ algorithm = BT_8723B_1ANT_COEX_ALGO_A2DP_PANHS;
+ else
+ algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR_A2DP;
+ }
+ }
+ } else if (numOfDiffProfile == 3) {
+ if (pBtLinkInfo->bScoExist) {
+ if (pBtLinkInfo->bHidExist && pBtLinkInfo->bA2dpExist) {
+ algorithm = BT_8723B_1ANT_COEX_ALGO_HID;
+ } else if (
+ pBtLinkInfo->bHidExist && pBtLinkInfo->bPanExist
+ ) {
+ if (bBtHsOn)
+ algorithm = BT_8723B_1ANT_COEX_ALGO_HID_A2DP;
+ else
+ algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR_HID;
+ } else if (pBtLinkInfo->bPanExist && pBtLinkInfo->bA2dpExist) {
+ if (bBtHsOn)
+ algorithm = BT_8723B_1ANT_COEX_ALGO_SCO;
+ else
+ algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR_HID;
+ }
+ } else {
+ if (
+ pBtLinkInfo->bHidExist &&
+ pBtLinkInfo->bPanExist &&
+ pBtLinkInfo->bA2dpExist
+ ) {
+ if (bBtHsOn)
+ algorithm = BT_8723B_1ANT_COEX_ALGO_HID_A2DP;
+ else
+ algorithm = BT_8723B_1ANT_COEX_ALGO_HID_A2DP_PANEDR;
+ }
+ }
+ } else if (numOfDiffProfile >= 3) {
+ if (pBtLinkInfo->bScoExist) {
+ if (
+ pBtLinkInfo->bHidExist &&
+ pBtLinkInfo->bPanExist &&
+ pBtLinkInfo->bA2dpExist
+ ) {
+ if (!bBtHsOn)
+ algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR_HID;
+
+ }
+ }
+ }
+
+ return algorithm;
+}
+
+static void halbtc8723b1ant_SetSwPenaltyTxRateAdaptive(
+ struct btc_coexist *pBtCoexist, bool bLowPenaltyRa
+)
+{
+ u8 H2C_Parameter[6] = {0};
+
+ H2C_Parameter[0] = 0x6; /* opCode, 0x6 = Retry_Penalty */
+
+ if (bLowPenaltyRa) {
+ H2C_Parameter[1] |= BIT0;
+ H2C_Parameter[2] = 0x00; /* normal rate except MCS7/6/5, OFDM54/48/36 */
+ H2C_Parameter[3] = 0xf7; /* MCS7 or OFDM54 */
+ H2C_Parameter[4] = 0xf8; /* MCS6 or OFDM48 */
+ H2C_Parameter[5] = 0xf9; /* MCS5 or OFDM36 */
+ }
+
+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x69, 6, H2C_Parameter);
+}
+
+static void halbtc8723b1ant_LowPenaltyRa(
+ struct btc_coexist *pBtCoexist, bool bForceExec, bool bLowPenaltyRa
+)
+{
+ pCoexDm->bCurLowPenaltyRa = bLowPenaltyRa;
+
+ if (!bForceExec) {
+ if (pCoexDm->bPreLowPenaltyRa == pCoexDm->bCurLowPenaltyRa)
+ return;
+ }
+ halbtc8723b1ant_SetSwPenaltyTxRateAdaptive(
+ pBtCoexist, pCoexDm->bCurLowPenaltyRa
+ );
+
+ pCoexDm->bPreLowPenaltyRa = pCoexDm->bCurLowPenaltyRa;
+}
+
+static void halbtc8723b1ant_SetCoexTable(
+ struct btc_coexist *pBtCoexist,
+ u32 val0x6c0,
+ u32 val0x6c4,
+ u32 val0x6c8,
+ u8 val0x6cc
+)
+{
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x6c0, val0x6c0);
+
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x6c4, val0x6c4);
+
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x6c8, val0x6c8);
+
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x6cc, val0x6cc);
+}
+
+static void halbtc8723b1ant_CoexTable(
+ struct btc_coexist *pBtCoexist,
+ bool bForceExec,
+ u32 val0x6c0,
+ u32 val0x6c4,
+ u32 val0x6c8,
+ u8 val0x6cc
+)
+{
+ pCoexDm->curVal0x6c0 = val0x6c0;
+ pCoexDm->curVal0x6c4 = val0x6c4;
+ pCoexDm->curVal0x6c8 = val0x6c8;
+ pCoexDm->curVal0x6cc = val0x6cc;
+
+ if (!bForceExec) {
+ if (
+ (pCoexDm->preVal0x6c0 == pCoexDm->curVal0x6c0) &&
+ (pCoexDm->preVal0x6c4 == pCoexDm->curVal0x6c4) &&
+ (pCoexDm->preVal0x6c8 == pCoexDm->curVal0x6c8) &&
+ (pCoexDm->preVal0x6cc == pCoexDm->curVal0x6cc)
+ )
+ return;
+ }
+
+ halbtc8723b1ant_SetCoexTable(
+ pBtCoexist, val0x6c0, val0x6c4, val0x6c8, val0x6cc
+ );
+
+ pCoexDm->preVal0x6c0 = pCoexDm->curVal0x6c0;
+ pCoexDm->preVal0x6c4 = pCoexDm->curVal0x6c4;
+ pCoexDm->preVal0x6c8 = pCoexDm->curVal0x6c8;
+ pCoexDm->preVal0x6cc = pCoexDm->curVal0x6cc;
+}
+
+static void halbtc8723b1ant_CoexTableWithType(
+ struct btc_coexist *pBtCoexist, bool bForceExec, u8 type
+)
+{
+ pCoexSta->nCoexTableType = type;
+
+ switch (type) {
+ case 0:
+ halbtc8723b1ant_CoexTable(
+ pBtCoexist, bForceExec, 0x55555555, 0x55555555, 0xffffff, 0x3
+ );
+ break;
+ case 1:
+ halbtc8723b1ant_CoexTable(
+ pBtCoexist, bForceExec, 0x55555555, 0x5a5a5a5a, 0xffffff, 0x3
+ );
+ break;
+ case 2:
+ halbtc8723b1ant_CoexTable(
+ pBtCoexist, bForceExec, 0x5a5a5a5a, 0x5a5a5a5a, 0xffffff, 0x3
+ );
+ break;
+ case 3:
+ halbtc8723b1ant_CoexTable(
+ pBtCoexist, bForceExec, 0xaaaa5555, 0xaaaa5a5a, 0xffffff, 0x3
+ );
+ break;
+ case 4:
+ halbtc8723b1ant_CoexTable(
+ pBtCoexist, bForceExec, 0x55555555, 0xaaaa5a5a, 0xffffff, 0x3
+ );
+ break;
+ case 5:
+ halbtc8723b1ant_CoexTable(
+ pBtCoexist, bForceExec, 0x5a5a5a5a, 0xaaaa5a5a, 0xffffff, 0x3
+ );
+ break;
+ case 6:
+ halbtc8723b1ant_CoexTable(
+ pBtCoexist, bForceExec, 0x55555555, 0xaaaaaaaa, 0xffffff, 0x3
+ );
+ break;
+ case 7:
+ halbtc8723b1ant_CoexTable(
+ pBtCoexist, bForceExec, 0xaaaaaaaa, 0xaaaaaaaa, 0xffffff, 0x3
+ );
+ break;
+ default:
+ break;
+ }
+}
+
+static void halbtc8723b1ant_SetFwIgnoreWlanAct(
+ struct btc_coexist *pBtCoexist, bool bEnable
+)
+{
+ u8 H2C_Parameter[1] = {0};
+
+ if (bEnable)
+ H2C_Parameter[0] |= BIT0; /* function enable */
+
+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x63, 1, H2C_Parameter);
+}
+
+static void halbtc8723b1ant_IgnoreWlanAct(
+ struct btc_coexist *pBtCoexist, bool bForceExec, bool bEnable
+)
+{
+ pCoexDm->bCurIgnoreWlanAct = bEnable;
+
+ if (!bForceExec) {
+ if (pCoexDm->bPreIgnoreWlanAct == pCoexDm->bCurIgnoreWlanAct)
+ return;
+ }
+ halbtc8723b1ant_SetFwIgnoreWlanAct(pBtCoexist, bEnable);
+
+ pCoexDm->bPreIgnoreWlanAct = pCoexDm->bCurIgnoreWlanAct;
+}
+
+static void halbtc8723b1ant_SetLpsRpwm(
+ struct btc_coexist *pBtCoexist, u8 lpsVal, u8 rpwmVal
+)
+{
+ u8 lps = lpsVal;
+ u8 rpwm = rpwmVal;
+
+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_U1_LPS_VAL, &lps);
+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_U1_RPWM_VAL, &rpwm);
+}
+
+static void halbtc8723b1ant_LpsRpwm(
+ struct btc_coexist *pBtCoexist, bool bForceExec, u8 lpsVal, u8 rpwmVal
+)
+{
+ pCoexDm->curLps = lpsVal;
+ pCoexDm->curRpwm = rpwmVal;
+
+ if (!bForceExec) {
+ if (
+ (pCoexDm->preLps == pCoexDm->curLps) &&
+ (pCoexDm->preRpwm == pCoexDm->curRpwm)
+ ) {
+ return;
+ }
+ }
+ halbtc8723b1ant_SetLpsRpwm(pBtCoexist, lpsVal, rpwmVal);
+
+ pCoexDm->preLps = pCoexDm->curLps;
+ pCoexDm->preRpwm = pCoexDm->curRpwm;
+}
+
+static void halbtc8723b1ant_SwMechanism(
+ struct btc_coexist *pBtCoexist, bool bLowPenaltyRA
+)
+{
+ halbtc8723b1ant_LowPenaltyRa(pBtCoexist, NORMAL_EXEC, bLowPenaltyRA);
+}
+
+static void halbtc8723b1ant_SetAntPath(
+ struct btc_coexist *pBtCoexist, u8 antPosType, bool bInitHwCfg, bool bWifiOff
+)
+{
+ struct btc_board_info *pBoardInfo = &pBtCoexist->boardInfo;
+ u32 fwVer = 0, u4Tmp = 0, cntBtCalChk = 0;
+ bool bPgExtSwitch = false;
+ bool bUseExtSwitch = false;
+ bool bIsInMpMode = false;
+ u8 H2C_Parameter[2] = {0}, u1Tmp = 0;
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_EXT_SWITCH, &bPgExtSwitch);
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_FW_VER, &fwVer); /* [31:16]=fw ver, [15:0]=fw sub ver */
+
+ if ((fwVer > 0 && fwVer < 0xc0000) || bPgExtSwitch)
+ bUseExtSwitch = true;
+
+ if (bInitHwCfg) {
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x780); /* WiFi TRx Mask on */
+ pBtCoexist->fBtcSetBtReg(pBtCoexist, BTC_BT_REG_RF, 0x3c, 0x15); /* BT TRx Mask on */
+
+ if (fwVer >= 0x180000) {
+ /* Use H2C to set GNT_BT to HIGH */
+ H2C_Parameter[0] = 1;
+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x6E, 1, H2C_Parameter);
+ } else /* set grant_bt to high */
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x765, 0x18);
+
+ /* set wlan_act control by PTA */
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x76e, 0x4);
+
+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x67, 0x20, 0x1); /* BT select s0/s1 is controlled by WiFi */
+
+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x39, 0x8, 0x1);
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x974, 0xff);
+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x944, 0x3, 0x3);
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x930, 0x77);
+ } else if (bWifiOff) {
+ if (fwVer >= 0x180000) {
+ /* Use H2C to set GNT_BT to HIGH */
+ H2C_Parameter[0] = 1;
+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x6E, 1, H2C_Parameter);
+ } else /* set grant_bt to high */
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x765, 0x18);
+
+ /* set wlan_act to always low */
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x76e, 0x4);
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_IS_IN_MP_MODE, &bIsInMpMode);
+ if (!bIsInMpMode)
+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x67, 0x20, 0x0); /* BT select s0/s1 is controlled by BT */
+ else
+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x67, 0x20, 0x1); /* BT select s0/s1 is controlled by WiFi */
+
+ /* 0x4c[24:23]= 00, Set Antenna control by BT_RFE_CTRL BT Vendor 0xac = 0xf002 */
+ u4Tmp = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x4c);
+ u4Tmp &= ~BIT23;
+ u4Tmp &= ~BIT24;
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x4c, u4Tmp);
+ } else {
+ /* Use H2C to set GNT_BT to LOW */
+ if (fwVer >= 0x180000) {
+ if (pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x765) != 0) {
+ H2C_Parameter[0] = 0;
+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x6E, 1, H2C_Parameter);
+ }
+ } else {
+ /* BT calibration check */
+ while (cntBtCalChk <= 20) {
+ u1Tmp = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x49d);
+ cntBtCalChk++;
+
+ if (u1Tmp & BIT0)
+ mdelay(50);
+ else
+ break;
+ }
+
+ /* set grant_bt to PTA */
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x765, 0x0);
+ }
+
+ if (pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x76e) != 0xc)
+ /* set wlan_act control by PTA */
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x76e, 0xc);
+ }
+
+ if (bUseExtSwitch) {
+ if (bInitHwCfg) {
+ /* 0x4c[23]= 0, 0x4c[24]= 1 Antenna control by WL/BT */
+ u4Tmp = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x4c);
+ u4Tmp &= ~BIT23;
+ u4Tmp |= BIT24;
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x4c, u4Tmp);
+
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x0); /* fixed internal switch S1->WiFi, S0->BT */
+
+ if (pBoardInfo->btdmAntPos == BTC_ANTENNA_AT_MAIN_PORT) {
+ /* tell firmware "no antenna inverse" */
+ H2C_Parameter[0] = 0;
+ H2C_Parameter[1] = 1; /* ext switch type */
+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x65, 2, H2C_Parameter);
+ } else {
+ /* tell firmware "antenna inverse" */
+ H2C_Parameter[0] = 1;
+ H2C_Parameter[1] = 1; /* ext switch type */
+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x65, 2, H2C_Parameter);
+ }
+ }
+
+
+ /* ext switch setting */
+ switch (antPosType) {
+ case BTC_ANT_PATH_WIFI:
+ if (pBoardInfo->btdmAntPos == BTC_ANTENNA_AT_MAIN_PORT)
+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x92c, 0x3, 0x1);
+ else
+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x92c, 0x3, 0x2);
+ break;
+ case BTC_ANT_PATH_BT:
+ if (pBoardInfo->btdmAntPos == BTC_ANTENNA_AT_MAIN_PORT)
+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x92c, 0x3, 0x2);
+ else
+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x92c, 0x3, 0x1);
+ break;
+ default:
+ case BTC_ANT_PATH_PTA:
+ if (pBoardInfo->btdmAntPos == BTC_ANTENNA_AT_MAIN_PORT)
+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x92c, 0x3, 0x1);
+ else
+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x92c, 0x3, 0x2);
+ break;
+ }
+
+ } else {
+ if (bInitHwCfg) {
+ /* 0x4c[23]= 1, 0x4c[24]= 0 Antenna control by 0x64 */
+ u4Tmp = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x4c);
+ u4Tmp |= BIT23;
+ u4Tmp &= ~BIT24;
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x4c, u4Tmp);
+
+ /* Fix Ext switch Main->S1, Aux->S0 */
+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x64, 0x1, 0x0);
+
+ if (pBoardInfo->btdmAntPos == BTC_ANTENNA_AT_MAIN_PORT) {
+
+ /* tell firmware "no antenna inverse" */
+ H2C_Parameter[0] = 0;
+ H2C_Parameter[1] = 0; /* internal switch type */
+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x65, 2, H2C_Parameter);
+ } else {
+
+ /* tell firmware "antenna inverse" */
+ H2C_Parameter[0] = 1;
+ H2C_Parameter[1] = 0; /* internal switch type */
+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x65, 2, H2C_Parameter);
+ }
+ }
+
+
+ /* internal switch setting */
+ switch (antPosType) {
+ case BTC_ANT_PATH_WIFI:
+ if (pBoardInfo->btdmAntPos == BTC_ANTENNA_AT_MAIN_PORT)
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x0);
+ else
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x280);
+ break;
+ case BTC_ANT_PATH_BT:
+ if (pBoardInfo->btdmAntPos == BTC_ANTENNA_AT_MAIN_PORT)
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x280);
+ else
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x0);
+ break;
+ default:
+ case BTC_ANT_PATH_PTA:
+ if (pBoardInfo->btdmAntPos == BTC_ANTENNA_AT_MAIN_PORT)
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x200);
+ else
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x80);
+ break;
+ }
+ }
+}
+
+static void halbtc8723b1ant_SetFwPstdma(
+ struct btc_coexist *pBtCoexist, u8 byte1, u8 byte2, u8 byte3, u8 byte4, u8 byte5
+)
+{
+ u8 H2C_Parameter[5] = {0};
+ u8 realByte1 = byte1, realByte5 = byte5;
+ bool bApEnable = false;
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_AP_MODE_ENABLE, &bApEnable);
+
+ if (bApEnable) {
+ if (byte1 & BIT4 && !(byte1 & BIT5)) {
+ realByte1 &= ~BIT4;
+ realByte1 |= BIT5;
+
+ realByte5 |= BIT5;
+ realByte5 &= ~BIT6;
+ }
+ }
+
+ H2C_Parameter[0] = realByte1;
+ H2C_Parameter[1] = byte2;
+ H2C_Parameter[2] = byte3;
+ H2C_Parameter[3] = byte4;
+ H2C_Parameter[4] = realByte5;
+
+ pCoexDm->psTdmaPara[0] = realByte1;
+ pCoexDm->psTdmaPara[1] = byte2;
+ pCoexDm->psTdmaPara[2] = byte3;
+ pCoexDm->psTdmaPara[3] = byte4;
+ pCoexDm->psTdmaPara[4] = realByte5;
+
+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x60, 5, H2C_Parameter);
+}
+
+
+static void halbtc8723b1ant_PsTdma(
+ struct btc_coexist *pBtCoexist, bool bForceExec, bool bTurnOn, u8 type
+)
+{
+ struct btc_bt_link_info *pBtLinkInfo = &pBtCoexist->btLinkInfo;
+ bool bWifiBusy = false;
+ u8 rssiAdjustVal = 0;
+ u8 psTdmaByte4Val = 0x50, psTdmaByte0Val = 0x51, psTdmaByte3Val = 0x10;
+ s8 nWiFiDurationAdjust = 0x0;
+ /* u32 fwVer = 0; */
+
+ pCoexDm->bCurPsTdmaOn = bTurnOn;
+ pCoexDm->curPsTdma = type;
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_BUSY, &bWifiBusy);
+
+ if (!bForceExec) {
+ if (
+ (pCoexDm->bPrePsTdmaOn == pCoexDm->bCurPsTdmaOn) &&
+ (pCoexDm->prePsTdma == pCoexDm->curPsTdma)
+ )
+ return;
+ }
+
+ if (pCoexSta->nScanAPNum <= 5)
+ nWiFiDurationAdjust = 5;
+ else if (pCoexSta->nScanAPNum >= 40)
+ nWiFiDurationAdjust = -15;
+ else if (pCoexSta->nScanAPNum >= 20)
+ nWiFiDurationAdjust = -10;
+
+ if (!pCoexSta->bForceLpsOn) { /* only for A2DP-only case 1/2/9/11 */
+ psTdmaByte0Val = 0x61; /* no null-pkt */
+ psTdmaByte3Val = 0x11; /* no tx-pause at BT-slot */
+ psTdmaByte4Val = 0x10; /* 0x778 = d/1 toggle */
+ }
+
+
+ if (bTurnOn) {
+ if (pBtLinkInfo->bSlaveRole)
+ psTdmaByte4Val = psTdmaByte4Val | 0x1; /* 0x778 = 0x1 at wifi slot (no blocking BT Low-Pri pkts) */
+
+
+ switch (type) {
+ default:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0x51, 0x1a, 0x1a, 0x0, psTdmaByte4Val
+ );
+ break;
+ case 1:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist,
+ psTdmaByte0Val,
+ 0x3a + nWiFiDurationAdjust,
+ 0x03,
+ psTdmaByte3Val,
+ psTdmaByte4Val
+ );
+ break;
+ case 2:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist,
+ psTdmaByte0Val,
+ 0x2d + nWiFiDurationAdjust,
+ 0x03,
+ psTdmaByte3Val,
+ psTdmaByte4Val
+ );
+ break;
+ case 3:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0x51, 0x1d, 0x1d, 0x0, 0x10
+ );
+ break;
+ case 4:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0x93, 0x15, 0x3, 0x14, 0x0
+ );
+ break;
+ case 5:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0x61, 0x15, 0x3, 0x11, 0x10
+ );
+ break;
+ case 6:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0x61, 0x20, 0x3, 0x11, 0x11
+ );
+ break;
+ case 7:
+ halbtc8723b1ant_SetFwPstdma(pBtCoexist, 0x13, 0xc, 0x5, 0x0, 0x0);
+ break;
+ case 8:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0x93, 0x25, 0x3, 0x10, 0x0
+ );
+ break;
+ case 9:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist,
+ psTdmaByte0Val,
+ 0x21,
+ 0x3,
+ psTdmaByte3Val,
+ psTdmaByte4Val
+ );
+ break;
+ case 10:
+ halbtc8723b1ant_SetFwPstdma(pBtCoexist, 0x13, 0xa, 0xa, 0x0, 0x40);
+ break;
+ case 11:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist,
+ psTdmaByte0Val,
+ 0x21,
+ 0x03,
+ psTdmaByte3Val,
+ psTdmaByte4Val
+ );
+ break;
+ case 12:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0x51, 0x0a, 0x0a, 0x0, 0x50
+ );
+ break;
+ case 13:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0x51, 0x12, 0x12, 0x0, 0x10
+ );
+ break;
+ case 14:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0x51, 0x21, 0x3, 0x10, psTdmaByte4Val
+ );
+ break;
+ case 15:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0x13, 0xa, 0x3, 0x8, 0x0
+ );
+ break;
+ case 16:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0x93, 0x15, 0x3, 0x10, 0x0
+ );
+ break;
+ case 18:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0x93, 0x25, 0x3, 0x10, 0x0
+ );
+ break;
+ case 20:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0x61, 0x3f, 0x03, 0x11, 0x10
+
+ );
+ break;
+ case 21:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0x61, 0x25, 0x03, 0x11, 0x11
+ );
+ break;
+ case 22:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0x61, 0x25, 0x03, 0x11, 0x10
+ );
+ break;
+ case 23:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0xe3, 0x25, 0x3, 0x31, 0x18
+ );
+ break;
+ case 24:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0xe3, 0x15, 0x3, 0x31, 0x18
+ );
+ break;
+ case 25:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0xe3, 0xa, 0x3, 0x31, 0x18
+ );
+ break;
+ case 26:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0xe3, 0xa, 0x3, 0x31, 0x18
+ );
+ break;
+ case 27:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0xe3, 0x25, 0x3, 0x31, 0x98
+ );
+ break;
+ case 28:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0x69, 0x25, 0x3, 0x31, 0x0
+ );
+ break;
+ case 29:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0xab, 0x1a, 0x1a, 0x1, 0x10
+ );
+ break;
+ case 30:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0x51, 0x30, 0x3, 0x10, 0x10
+ );
+ break;
+ case 31:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0xd3, 0x1a, 0x1a, 0x0, 0x58
+ );
+ break;
+ case 32:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0x61, 0x35, 0x3, 0x11, 0x11
+ );
+ break;
+ case 33:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0xa3, 0x25, 0x3, 0x30, 0x90
+ );
+ break;
+ case 34:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0x53, 0x1a, 0x1a, 0x0, 0x10
+ );
+ break;
+ case 35:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0x63, 0x1a, 0x1a, 0x0, 0x10
+ );
+ break;
+ case 36:
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0xd3, 0x12, 0x3, 0x14, 0x50
+ );
+ break;
+ case 40: /* SoftAP only with no sta associated, BT disable , TDMA mode for power saving */
+ /* here softap mode screen off will cost 70-80mA for phone */
+ halbtc8723b1ant_SetFwPstdma(
+ pBtCoexist, 0x23, 0x18, 0x00, 0x10, 0x24
+ );
+ break;
+ }
+ } else {
+
+ /* disable PS tdma */
+ switch (type) {
+ case 8: /* PTA Control */
+ halbtc8723b1ant_SetFwPstdma(pBtCoexist, 0x8, 0x0, 0x0, 0x0, 0x0);
+ halbtc8723b1ant_SetAntPath(
+ pBtCoexist, BTC_ANT_PATH_PTA, false, false
+ );
+ break;
+ case 0:
+ default: /* Software control, Antenna at BT side */
+ halbtc8723b1ant_SetFwPstdma(pBtCoexist, 0x0, 0x0, 0x0, 0x0, 0x0);
+ halbtc8723b1ant_SetAntPath(
+ pBtCoexist, BTC_ANT_PATH_BT, false, false
+ );
+ break;
+ case 9: /* Software control, Antenna at WiFi side */
+ halbtc8723b1ant_SetFwPstdma(pBtCoexist, 0x0, 0x0, 0x0, 0x0, 0x0);
+ halbtc8723b1ant_SetAntPath(
+ pBtCoexist, BTC_ANT_PATH_WIFI, false, false
+ );
+ break;
+ }
+ }
+
+ rssiAdjustVal = 0;
+ pBtCoexist->fBtcSet(
+ pBtCoexist, BTC_SET_U1_RSSI_ADJ_VAL_FOR_1ANT_COEX_TYPE, &rssiAdjustVal
+ );
+
+ /* update pre state */
+ pCoexDm->bPrePsTdmaOn = pCoexDm->bCurPsTdmaOn;
+ pCoexDm->prePsTdma = pCoexDm->curPsTdma;
+}
+
+static bool halbtc8723b1ant_IsCommonAction(struct btc_coexist *pBtCoexist)
+{
+ bool bCommon = false, bWifiConnected = false, bWifiBusy = false;
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_CONNECTED, &bWifiConnected);
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_BUSY, &bWifiBusy);
+
+ if (
+ !bWifiConnected &&
+ pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE
+ ) {
+ /* halbtc8723b1ant_SwMechanism(pBtCoexist, false); */
+
+ bCommon = true;
+ } else if (
+ bWifiConnected &&
+ (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE)
+ ) {
+ /* halbtc8723b1ant_SwMechanism(pBtCoexist, false); */
+
+ bCommon = true;
+ } else if (
+ !bWifiConnected &&
+ (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE)
+ ) {
+ /* halbtc8723b1ant_SwMechanism(pBtCoexist, false); */
+
+ bCommon = true;
+ } else if (
+ bWifiConnected &&
+ (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE)
+ ) {
+ /* halbtc8723b1ant_SwMechanism(pBtCoexist, false); */
+
+ bCommon = true;
+ } else if (
+ !bWifiConnected &&
+ (pCoexDm->btStatus != BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE)
+ ) {
+ /* halbtc8723b1ant_SwMechanism(pBtCoexist, false); */
+
+ bCommon = true;
+ } else {
+ bCommon = false;
+ }
+
+ return bCommon;
+}
+
+
+static void halbtc8723b1ant_TdmaDurationAdjustForAcl(
+ struct btc_coexist *pBtCoexist, u8 wifiStatus
+)
+{
+ static s32 up, dn, m, n, WaitCount;
+ s32 result; /* 0: no change, +1: increase WiFi duration, -1: decrease WiFi duration */
+ u8 retryCount = 0, btInfoExt;
+
+ if (
+ (wifiStatus == BT_8723B_1ANT_WIFI_STATUS_NON_CONNECTED_ASSO_AUTH_SCAN) ||
+ (wifiStatus == BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN) ||
+ (wifiStatus == BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SPECIAL_PKT)
+ ) {
+ if (
+ pCoexDm->curPsTdma != 1 &&
+ pCoexDm->curPsTdma != 2 &&
+ pCoexDm->curPsTdma != 3 &&
+ pCoexDm->curPsTdma != 9
+ ) {
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 9);
+ pCoexDm->psTdmaDuAdjType = 9;
+
+ up = 0;
+ dn = 0;
+ m = 1;
+ n = 3;
+ result = 0;
+ WaitCount = 0;
+ }
+ return;
+ }
+
+ if (!pCoexDm->bAutoTdmaAdjust) {
+ pCoexDm->bAutoTdmaAdjust = true;
+
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 2);
+ pCoexDm->psTdmaDuAdjType = 2;
+ /* */
+ up = 0;
+ dn = 0;
+ m = 1;
+ n = 3;
+ result = 0;
+ WaitCount = 0;
+ } else {
+ /* acquire the BT TRx retry count from BT_Info byte2 */
+ retryCount = pCoexSta->btRetryCnt;
+ btInfoExt = pCoexSta->btInfoExt;
+
+ if (pCoexSta->lowPriorityTx > 1050 || pCoexSta->lowPriorityRx > 1250)
+ retryCount++;
+
+ result = 0;
+ WaitCount++;
+
+ if (retryCount == 0) { /* no retry in the last 2-second duration */
+ up++;
+ dn--;
+
+ if (dn <= 0)
+ dn = 0;
+
+ if (up >= n) { /* if 連續 n 個2秒 retry count為0, 則調寬WiFi duration */
+ WaitCount = 0;
+ n = 3;
+ up = 0;
+ dn = 0;
+ result = 1;
+ }
+ } else if (retryCount <= 3) { /* <=3 retry in the last 2-second duration */
+ up--;
+ dn++;
+
+ if (up <= 0)
+ up = 0;
+
+ if (dn == 2) { /* if 連續 2 個2秒 retry count< 3, 則調窄WiFi duration */
+ if (WaitCount <= 2)
+ m++; /* 避免一直在兩個level中來回 */
+ else
+ m = 1;
+
+ if (m >= 20) /* m 最大值 = 20 ' 最大120秒 recheck是否調整 WiFi duration. */
+ m = 20;
+
+ n = 3 * m;
+ up = 0;
+ dn = 0;
+ WaitCount = 0;
+ result = -1;
+ }
+ } else { /* retry count > 3, 只要1次 retry count > 3, 則調窄WiFi duration */
+ if (WaitCount == 1)
+ m++; /* 避免一直在兩個level中來回 */
+ else
+ m = 1;
+
+ if (m >= 20) /* m 最大值 = 20 ' 最大120秒 recheck是否調整 WiFi duration. */
+ m = 20;
+
+ n = 3 * m;
+ up = 0;
+ dn = 0;
+ WaitCount = 0;
+ result = -1;
+ }
+
+ if (result == -1) {
+ if (
+ BT_INFO_8723B_1ANT_A2DP_BASIC_RATE(btInfoExt) &&
+ ((pCoexDm->curPsTdma == 1) || (pCoexDm->curPsTdma == 2))
+ ) {
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 9);
+ pCoexDm->psTdmaDuAdjType = 9;
+ } else if (pCoexDm->curPsTdma == 1) {
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 2);
+ pCoexDm->psTdmaDuAdjType = 2;
+ } else if (pCoexDm->curPsTdma == 2) {
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 9);
+ pCoexDm->psTdmaDuAdjType = 9;
+ } else if (pCoexDm->curPsTdma == 9) {
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 11);
+ pCoexDm->psTdmaDuAdjType = 11;
+ }
+ } else if (result == 1) {
+ if (
+ BT_INFO_8723B_1ANT_A2DP_BASIC_RATE(btInfoExt) &&
+ ((pCoexDm->curPsTdma == 1) || (pCoexDm->curPsTdma == 2))
+ ) {
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 9);
+ pCoexDm->psTdmaDuAdjType = 9;
+ } else if (pCoexDm->curPsTdma == 11) {
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 9);
+ pCoexDm->psTdmaDuAdjType = 9;
+ } else if (pCoexDm->curPsTdma == 9) {
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 2);
+ pCoexDm->psTdmaDuAdjType = 2;
+ } else if (pCoexDm->curPsTdma == 2) {
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 1);
+ pCoexDm->psTdmaDuAdjType = 1;
+ }
+ }
+
+ if (
+ pCoexDm->curPsTdma != 1 &&
+ pCoexDm->curPsTdma != 2 &&
+ pCoexDm->curPsTdma != 9 &&
+ pCoexDm->curPsTdma != 11
+ ) /* recover to previous adjust type */
+ halbtc8723b1ant_PsTdma(
+ pBtCoexist, NORMAL_EXEC, true, pCoexDm->psTdmaDuAdjType
+ );
+ }
+}
+
+static void halbtc8723b1ant_PsTdmaCheckForPowerSaveState(
+ struct btc_coexist *pBtCoexist, bool bNewPsState
+)
+{
+ u8 lpsMode = 0x0;
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U1_LPS_MODE, &lpsMode);
+
+ if (lpsMode) { /* already under LPS state */
+ if (bNewPsState) {
+ /* keep state under LPS, do nothing. */
+ } else /* will leave LPS state, turn off psTdma first */
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 0);
+ } else { /* NO PS state */
+ if (bNewPsState) /* will enter LPS state, turn off psTdma first */
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 0);
+ else {
+ /* keep state under NO PS state, do nothing. */
+ }
+ }
+}
+
+static void halbtc8723b1ant_PowerSaveState(
+ struct btc_coexist *pBtCoexist, u8 psType, u8 lpsVal, u8 rpwmVal
+)
+{
+ bool bLowPwrDisable = false;
+
+ switch (psType) {
+ case BTC_PS_WIFI_NATIVE:
+ /* recover to original 32k low power setting */
+ bLowPwrDisable = false;
+ pBtCoexist->fBtcSet(
+ pBtCoexist, BTC_SET_ACT_DISABLE_LOW_POWER, &bLowPwrDisable
+ );
+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_ACT_NORMAL_LPS, NULL);
+ pCoexSta->bForceLpsOn = false;
+ break;
+ case BTC_PS_LPS_ON:
+ halbtc8723b1ant_PsTdmaCheckForPowerSaveState(pBtCoexist, true);
+ halbtc8723b1ant_LpsRpwm(pBtCoexist, NORMAL_EXEC, lpsVal, rpwmVal);
+ /* when coex force to enter LPS, do not enter 32k low power. */
+ bLowPwrDisable = true;
+ pBtCoexist->fBtcSet(
+ pBtCoexist, BTC_SET_ACT_DISABLE_LOW_POWER, &bLowPwrDisable
+ );
+ /* power save must executed before psTdma. */
+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_ACT_ENTER_LPS, NULL);
+ pCoexSta->bForceLpsOn = true;
+ break;
+ case BTC_PS_LPS_OFF:
+ halbtc8723b1ant_PsTdmaCheckForPowerSaveState(pBtCoexist, false);
+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_ACT_LEAVE_LPS, NULL);
+ pCoexSta->bForceLpsOn = false;
+ break;
+ default:
+ break;
+ }
+}
+
+/* */
+/* */
+/* Software Coex Mechanism start */
+/* */
+/* */
+
+/* */
+/* */
+/* Non-Software Coex Mechanism start */
+/* */
+/* */
+static void halbtc8723b1ant_ActionWifiMultiPort(struct btc_coexist *pBtCoexist)
+{
+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
+
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 8);
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 2);
+}
+
+static void halbtc8723b1ant_ActionHs(struct btc_coexist *pBtCoexist)
+{
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 5);
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 2);
+}
+
+static void halbtc8723b1ant_ActionBtInquiry(struct btc_coexist *pBtCoexist)
+{
+ struct btc_bt_link_info *pBtLinkInfo = &pBtCoexist->btLinkInfo;
+ bool bWifiConnected = false;
+ bool bApEnable = false;
+ bool bWifiBusy = false;
+ bool bBtBusy = false;
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_AP_MODE_ENABLE, &bApEnable);
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_CONNECTED, &bWifiConnected);
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_BUSY, &bWifiBusy);
+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_BL_BT_TRAFFIC_BUSY, &bBtBusy);
+
+ if (!bWifiConnected && !pCoexSta->bWiFiIsHighPriTask) {
+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 8);
+
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 0);
+ } else if (
+ pBtLinkInfo->bScoExist ||
+ pBtLinkInfo->bHidExist ||
+ pBtLinkInfo->bA2dpExist
+ ) {
+ /* SCO/HID/A2DP busy */
+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 32);
+
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
+ } else if (pBtLinkInfo->bPanExist || bWifiBusy) {
+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 20);
+
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
+ } else {
+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 8);
+
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 7);
+ }
+}
+
+static void halbtc8723b1ant_ActionBtScoHidOnlyBusy(
+ struct btc_coexist *pBtCoexist, u8 wifiStatus
+)
+{
+ struct btc_bt_link_info *pBtLinkInfo = &pBtCoexist->btLinkInfo;
+ bool bWifiConnected = false;
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_CONNECTED, &bWifiConnected);
+
+ /* tdma and coex table */
+
+ if (pBtLinkInfo->bScoExist) {
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 5);
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 5);
+ } else { /* HID */
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 6);
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 5);
+ }
+}
+
+static void halbtc8723b1ant_ActionWifiConnectedBtAclBusy(
+ struct btc_coexist *pBtCoexist, u8 wifiStatus
+)
+{
+ struct btc_bt_link_info *pBtLinkInfo = &pBtCoexist->btLinkInfo;
+
+ halbtc8723b1ant_BtRssiState(2, 28, 0);
+
+ if ((pCoexSta->lowPriorityRx >= 1000) && (pCoexSta->lowPriorityRx != 65535))
+ pBtLinkInfo->bSlaveRole = true;
+ else
+ pBtLinkInfo->bSlaveRole = false;
+
+ if (pBtLinkInfo->bHidOnly) { /* HID */
+ halbtc8723b1ant_ActionBtScoHidOnlyBusy(pBtCoexist, wifiStatus);
+ pCoexDm->bAutoTdmaAdjust = false;
+ return;
+ } else if (pBtLinkInfo->bA2dpOnly) { /* A2DP */
+ if (wifiStatus == BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE) {
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 32);
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
+ pCoexDm->bAutoTdmaAdjust = false;
+ } else {
+ halbtc8723b1ant_TdmaDurationAdjustForAcl(pBtCoexist, wifiStatus);
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
+ pCoexDm->bAutoTdmaAdjust = true;
+ }
+ } else if (pBtLinkInfo->bHidExist && pBtLinkInfo->bA2dpExist) { /* HID+A2DP */
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 14);
+ pCoexDm->bAutoTdmaAdjust = false;
+
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
+ } else if (
+ pBtLinkInfo->bPanOnly ||
+ (pBtLinkInfo->bHidExist && pBtLinkInfo->bPanExist)
+ ) { /* PAN(OPP, FTP), HID+PAN(OPP, FTP) */
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 3);
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
+ pCoexDm->bAutoTdmaAdjust = false;
+ } else if (
+ (pBtLinkInfo->bA2dpExist && pBtLinkInfo->bPanExist) ||
+ (pBtLinkInfo->bHidExist && pBtLinkInfo->bA2dpExist && pBtLinkInfo->bPanExist)
+ ) { /* A2DP+PAN(OPP, FTP), HID+A2DP+PAN(OPP, FTP) */
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 13);
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
+ pCoexDm->bAutoTdmaAdjust = false;
+ } else {
+ /* BT no-profile busy (0x9) */
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 32);
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
+ pCoexDm->bAutoTdmaAdjust = false;
+ }
+}
+
+static void halbtc8723b1ant_ActionWifiNotConnected(struct btc_coexist *pBtCoexist)
+{
+ /* power save state */
+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
+
+ /* tdma and coex table */
+ halbtc8723b1ant_PsTdma(pBtCoexist, FORCE_EXEC, false, 8);
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 0);
+}
+
+static void halbtc8723b1ant_ActionWifiNotConnectedScan(
+ struct btc_coexist *pBtCoexist
+)
+{
+ struct btc_bt_link_info *pBtLinkInfo = &pBtCoexist->btLinkInfo;
+
+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
+
+ /* tdma and coex table */
+ if (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_BUSY) {
+ if (pBtLinkInfo->bA2dpExist) {
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 32);
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
+ } else if (pBtLinkInfo->bA2dpExist && pBtLinkInfo->bPanExist) {
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 22);
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
+ } else {
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 20);
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
+ }
+ } else if (
+ (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_SCO_BUSY) ||
+ (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY)
+ ) {
+ halbtc8723b1ant_ActionBtScoHidOnlyBusy(
+ pBtCoexist, BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN
+ );
+ } else {
+ /* Bryant Add */
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 8);
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 2);
+ }
+}
+
+static void halbtc8723b1ant_ActionWifiNotConnectedAssoAuth(
+ struct btc_coexist *pBtCoexist
+)
+{
+ struct btc_bt_link_info *pBtLinkInfo = &pBtCoexist->btLinkInfo;
+
+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
+
+ /* tdma and coex table */
+ if (
+ (pBtLinkInfo->bScoExist) ||
+ (pBtLinkInfo->bHidExist) ||
+ (pBtLinkInfo->bA2dpExist)
+ ) {
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 32);
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
+ } else if (pBtLinkInfo->bPanExist) {
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 20);
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
+ } else {
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 8);
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 2);
+ }
+}
+
+static void halbtc8723b1ant_ActionWifiConnectedScan(struct btc_coexist *pBtCoexist)
+{
+ struct btc_bt_link_info *pBtLinkInfo = &pBtCoexist->btLinkInfo;
+
+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
+
+ /* tdma and coex table */
+ if (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_BUSY) {
+ if (pBtLinkInfo->bA2dpExist) {
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 32);
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
+ } else if (pBtLinkInfo->bA2dpExist && pBtLinkInfo->bPanExist) {
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 22);
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
+ } else {
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 20);
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
+ }
+ } else if (
+ (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_SCO_BUSY) ||
+ (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY)
+ ) {
+ halbtc8723b1ant_ActionBtScoHidOnlyBusy(
+ pBtCoexist, BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN
+ );
+ } else {
+ /* Bryant Add */
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 8);
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 2);
+ }
+}
+
+static void halbtc8723b1ant_ActionWifiConnectedSpecialPacket(
+ struct btc_coexist *pBtCoexist
+)
+{
+ struct btc_bt_link_info *pBtLinkInfo = &pBtCoexist->btLinkInfo;
+
+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
+
+ /* tdma and coex table */
+ if (
+ (pBtLinkInfo->bScoExist) ||
+ (pBtLinkInfo->bHidExist) ||
+ (pBtLinkInfo->bA2dpExist)
+ ) {
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 32);
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
+ } else if (pBtLinkInfo->bPanExist) {
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 20);
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
+ } else {
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 8);
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 2);
+ }
+}
+
+static void halbtc8723b1ant_ActionWifiConnected(struct btc_coexist *pBtCoexist)
+{
+ bool bWifiBusy = false;
+ bool bScan = false, bLink = false, bRoam = false;
+ bool bUnder4way = false, bApEnable = false;
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_4_WAY_PROGRESS, &bUnder4way);
+ if (bUnder4way) {
+ halbtc8723b1ant_ActionWifiConnectedSpecialPacket(pBtCoexist);
+ return;
+ }
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_SCAN, &bScan);
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_LINK, &bLink);
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_ROAM, &bRoam);
+ if (bScan || bLink || bRoam) {
+ if (bScan)
+ halbtc8723b1ant_ActionWifiConnectedScan(pBtCoexist);
+ else
+ halbtc8723b1ant_ActionWifiConnectedSpecialPacket(pBtCoexist);
+ return;
+ }
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_AP_MODE_ENABLE, &bApEnable);
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_BUSY, &bWifiBusy);
+
+ /* power save state */
+ if (
+ !bApEnable &&
+ pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_BUSY &&
+ !pBtCoexist->btLinkInfo.bHidOnly
+ ) {
+ if (pBtCoexist->btLinkInfo.bA2dpOnly) { /* A2DP */
+ if (!bWifiBusy)
+ halbtc8723b1ant_PowerSaveState(
+ pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0
+ );
+ else { /* busy */
+ if (pCoexSta->nScanAPNum >= BT_8723B_1ANT_WIFI_NOISY_THRESH) /* no force LPS, no PS-TDMA, use pure TDMA */
+ halbtc8723b1ant_PowerSaveState(
+ pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0
+ );
+ else
+ halbtc8723b1ant_PowerSaveState(
+ pBtCoexist, BTC_PS_LPS_ON, 0x50, 0x4
+ );
+ }
+ } else if (
+ (!pCoexSta->bPanExist) &&
+ (!pCoexSta->bA2dpExist) &&
+ (!pCoexSta->bHidExist)
+ )
+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
+ else
+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_LPS_ON, 0x50, 0x4);
+ } else
+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
+
+ /* tdma and coex table */
+ if (!bWifiBusy) {
+ if (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_BUSY) {
+ halbtc8723b1ant_ActionWifiConnectedBtAclBusy(
+ pBtCoexist,
+ BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE
+ );
+ } else if (
+ (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_SCO_BUSY) ||
+ (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY)
+ ) {
+ halbtc8723b1ant_ActionBtScoHidOnlyBusy(pBtCoexist,
+ BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE);
+ } else {
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 8);
+
+ if ((pCoexSta->highPriorityTx) + (pCoexSta->highPriorityRx) <= 60)
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 7);
+ }
+ } else {
+ if (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_BUSY) {
+ halbtc8723b1ant_ActionWifiConnectedBtAclBusy(
+ pBtCoexist,
+ BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY
+ );
+ } else if (
+ (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_SCO_BUSY) ||
+ (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY)
+ ) {
+ halbtc8723b1ant_ActionBtScoHidOnlyBusy(
+ pBtCoexist,
+ BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY
+ );
+ } else {
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 8);
+
+ if ((pCoexSta->highPriorityTx) + (pCoexSta->highPriorityRx) <= 60)
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 7);
+ }
+ }
+}
+
+static void halbtc8723b1ant_RunSwCoexistMechanism(struct btc_coexist *pBtCoexist)
+{
+ u8 algorithm = 0;
+
+ algorithm = halbtc8723b1ant_ActionAlgorithm(pBtCoexist);
+ pCoexDm->curAlgorithm = algorithm;
+
+ if (halbtc8723b1ant_IsCommonAction(pBtCoexist)) {
+
+ } else {
+ switch (pCoexDm->curAlgorithm) {
+ case BT_8723B_1ANT_COEX_ALGO_SCO:
+ /* halbtc8723b1ant_ActionSco(pBtCoexist); */
+ break;
+ case BT_8723B_1ANT_COEX_ALGO_HID:
+ /* halbtc8723b1ant_ActionHid(pBtCoexist); */
+ break;
+ case BT_8723B_1ANT_COEX_ALGO_A2DP:
+ /* halbtc8723b1ant_ActionA2dp(pBtCoexist); */
+ break;
+ case BT_8723B_1ANT_COEX_ALGO_A2DP_PANHS:
+ /* halbtc8723b1ant_ActionA2dpPanHs(pBtCoexist); */
+ break;
+ case BT_8723B_1ANT_COEX_ALGO_PANEDR:
+ /* halbtc8723b1ant_ActionPanEdr(pBtCoexist); */
+ break;
+ case BT_8723B_1ANT_COEX_ALGO_PANHS:
+ /* halbtc8723b1ant_ActionPanHs(pBtCoexist); */
+ break;
+ case BT_8723B_1ANT_COEX_ALGO_PANEDR_A2DP:
+ /* halbtc8723b1ant_ActionPanEdrA2dp(pBtCoexist); */
+ break;
+ case BT_8723B_1ANT_COEX_ALGO_PANEDR_HID:
+ /* halbtc8723b1ant_ActionPanEdrHid(pBtCoexist); */
+ break;
+ case BT_8723B_1ANT_COEX_ALGO_HID_A2DP_PANEDR:
+ /* halbtc8723b1ant_ActionHidA2dpPanEdr(pBtCoexist); */
+ break;
+ case BT_8723B_1ANT_COEX_ALGO_HID_A2DP:
+ /* halbtc8723b1ant_ActionHidA2dp(pBtCoexist); */
+ break;
+ default:
+ break;
+ }
+ pCoexDm->preAlgorithm = pCoexDm->curAlgorithm;
+ }
+}
+
+static void halbtc8723b1ant_RunCoexistMechanism(struct btc_coexist *pBtCoexist)
+{
+ struct btc_bt_link_info *pBtLinkInfo = &pBtCoexist->btLinkInfo;
+ bool bWifiConnected = false, bBtHsOn = false;
+ bool bIncreaseScanDevNum = false;
+ bool bBtCtrlAggBufSize = false;
+ u8 aggBufSize = 5;
+ u32 wifiLinkStatus = 0;
+ u32 numOfWifiLink = 0;
+
+ if (pBtCoexist->bManualControl)
+ return;
+
+ if (pBtCoexist->bStopCoexDm)
+ return;
+
+ if (pCoexSta->bUnderIps)
+ return;
+
+ if (
+ (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_BUSY) ||
+ (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_SCO_BUSY) ||
+ (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY)
+ ){
+ bIncreaseScanDevNum = true;
+ }
+
+ pBtCoexist->fBtcSet(
+ pBtCoexist,
+ BTC_SET_BL_INC_SCAN_DEV_NUM,
+ &bIncreaseScanDevNum
+ );
+ pBtCoexist->fBtcGet(
+ pBtCoexist,
+ BTC_GET_BL_WIFI_CONNECTED,
+ &bWifiConnected
+ );
+
+ pBtCoexist->fBtcGet(
+ pBtCoexist,
+ BTC_GET_U4_WIFI_LINK_STATUS,
+ &wifiLinkStatus
+ );
+ numOfWifiLink = wifiLinkStatus >> 16;
+
+ if ((numOfWifiLink >= 2) || (wifiLinkStatus & WIFI_P2P_GO_CONNECTED)) {
+ halbtc8723b1ant_LimitedTx(pBtCoexist, NORMAL_EXEC, 0, 0, 0, 0);
+ halbtc8723b1ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, bBtCtrlAggBufSize, aggBufSize);
+
+ if ((pBtLinkInfo->bA2dpExist) && (pCoexSta->bC2hBtInquiryPage))
+ halbtc8723b1ant_ActionBtInquiry(pBtCoexist);
+ else
+ halbtc8723b1ant_ActionWifiMultiPort(pBtCoexist);
+
+ return;
+ }
+
+ if ((pBtLinkInfo->bBtLinkExist) && (bWifiConnected)) {
+ halbtc8723b1ant_LimitedTx(pBtCoexist, NORMAL_EXEC, 1, 1, 0, 1);
+
+ if (pBtLinkInfo->bScoExist)
+ halbtc8723b1ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, true, 0x5);
+ else
+ halbtc8723b1ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, true, 0x8);
+
+ halbtc8723b1ant_SwMechanism(pBtCoexist, true);
+ halbtc8723b1ant_RunSwCoexistMechanism(pBtCoexist); /* just print debug message */
+ } else {
+ halbtc8723b1ant_LimitedTx(pBtCoexist, NORMAL_EXEC, 0, 0, 0, 0);
+
+ halbtc8723b1ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x5);
+
+ halbtc8723b1ant_SwMechanism(pBtCoexist, false);
+ halbtc8723b1ant_RunSwCoexistMechanism(pBtCoexist); /* just print debug message */
+ }
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn);
+ if (pCoexSta->bC2hBtInquiryPage) {
+ halbtc8723b1ant_ActionBtInquiry(pBtCoexist);
+ return;
+ } else if (bBtHsOn) {
+ halbtc8723b1ant_ActionHs(pBtCoexist);
+ return;
+ }
+
+
+ if (!bWifiConnected) {
+ bool bScan = false, bLink = false, bRoam = false;
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_SCAN, &bScan);
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_LINK, &bLink);
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_ROAM, &bRoam);
+
+ if (bScan || bLink || bRoam) {
+ if (bScan)
+ halbtc8723b1ant_ActionWifiNotConnectedScan(pBtCoexist);
+ else
+ halbtc8723b1ant_ActionWifiNotConnectedAssoAuth(pBtCoexist);
+ } else
+ halbtc8723b1ant_ActionWifiNotConnected(pBtCoexist);
+ } else /* wifi LPS/Busy */
+ halbtc8723b1ant_ActionWifiConnected(pBtCoexist);
+}
+
+static void halbtc8723b1ant_InitCoexDm(struct btc_coexist *pBtCoexist)
+{
+ /* force to reset coex mechanism */
+
+ /* sw all off */
+ halbtc8723b1ant_SwMechanism(pBtCoexist, false);
+
+ /* halbtc8723b1ant_PsTdma(pBtCoexist, FORCE_EXEC, false, 8); */
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, FORCE_EXEC, 0);
+
+ pCoexSta->popEventCnt = 0;
+}
+
+static void halbtc8723b1ant_InitHwConfig(
+ struct btc_coexist *pBtCoexist,
+ bool bBackUp,
+ bool bWifiOnly
+)
+{
+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x550, 0x8, 0x1); /* enable TBTT nterrupt */
+
+ /* 0x790[5:0]= 0x5 */
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x790, 0x5);
+
+ /* Enable counter statistics */
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x778, 0x1);
+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x40, 0x20, 0x1);
+
+ /* Antenna config */
+ if (bWifiOnly) {
+ halbtc8723b1ant_SetAntPath(pBtCoexist, BTC_ANT_PATH_WIFI, true, false);
+ halbtc8723b1ant_PsTdma(pBtCoexist, FORCE_EXEC, false, 9);
+ } else
+ halbtc8723b1ant_SetAntPath(pBtCoexist, BTC_ANT_PATH_BT, true, false);
+
+ /* PTA parameter */
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, FORCE_EXEC, 0);
+
+ pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x948);
+ pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x765);
+ pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x67);
+}
+
+/* */
+/* work around function start with wa_halbtc8723b1ant_ */
+/* */
+/* */
+/* extern function start with EXhalbtc8723b1ant_ */
+/* */
+void EXhalbtc8723b1ant_PowerOnSetting(struct btc_coexist *pBtCoexist)
+{
+ struct btc_board_info *pBoardInfo = &pBtCoexist->boardInfo;
+ u8 u1Tmp = 0x0;
+ u16 u2Tmp = 0x0;
+
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x67, 0x20);
+
+ /* enable BB, REG_SYS_FUNC_EN such that we can write 0x948 correctly. */
+ u2Tmp = pBtCoexist->fBtcRead2Byte(pBtCoexist, 0x2);
+ pBtCoexist->fBtcWrite2Byte(pBtCoexist, 0x2, u2Tmp | BIT0 | BIT1);
+
+ /* set GRAN_BT = 1 */
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x765, 0x18);
+ /* set WLAN_ACT = 0 */
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x76e, 0x4);
+
+ /* */
+ /* S0 or S1 setting and Local register setting(By the setting fw can get ant number, S0/S1, ... info) */
+ /* Local setting bit define */
+ /* BIT0: "0" for no antenna inverse; "1" for antenna inverse */
+ /* BIT1: "0" for internal switch; "1" for external switch */
+ /* BIT2: "0" for one antenna; "1" for two antenna */
+ /* NOTE: here default all internal switch and 1-antenna ==> BIT1 = 0 and BIT2 = 0 */
+ if (pBtCoexist->chipInterface == BTC_INTF_USB) {
+ /* fixed at S0 for USB interface */
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x0);
+
+ u1Tmp |= 0x1; /* antenna inverse */
+ pBtCoexist->fBtcWriteLocalReg1Byte(pBtCoexist, 0xfe08, u1Tmp);
+
+ pBoardInfo->btdmAntPos = BTC_ANTENNA_AT_AUX_PORT;
+ } else {
+ /* for PCIE and SDIO interface, we check efuse 0xc3[6] */
+ if (pBoardInfo->singleAntPath == 0) {
+ /* set to S1 */
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x280);
+ pBoardInfo->btdmAntPos = BTC_ANTENNA_AT_MAIN_PORT;
+ } else if (pBoardInfo->singleAntPath == 1) {
+ /* set to S0 */
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x0);
+ u1Tmp |= 0x1; /* antenna inverse */
+ pBoardInfo->btdmAntPos = BTC_ANTENNA_AT_AUX_PORT;
+ }
+
+ if (pBtCoexist->chipInterface == BTC_INTF_PCI)
+ pBtCoexist->fBtcWriteLocalReg1Byte(pBtCoexist, 0x384, u1Tmp);
+ else if (pBtCoexist->chipInterface == BTC_INTF_SDIO)
+ pBtCoexist->fBtcWriteLocalReg1Byte(pBtCoexist, 0x60, u1Tmp);
+ }
+}
+
+void EXhalbtc8723b1ant_InitHwConfig(struct btc_coexist *pBtCoexist, bool bWifiOnly)
+{
+ halbtc8723b1ant_InitHwConfig(pBtCoexist, true, bWifiOnly);
+}
+
+void EXhalbtc8723b1ant_InitCoexDm(struct btc_coexist *pBtCoexist)
+{
+ pBtCoexist->bStopCoexDm = false;
+
+ halbtc8723b1ant_InitCoexDm(pBtCoexist);
+
+ halbtc8723b1ant_QueryBtInfo(pBtCoexist);
+}
+
+void EXhalbtc8723b1ant_IpsNotify(struct btc_coexist *pBtCoexist, u8 type)
+{
+ if (pBtCoexist->bManualControl || pBtCoexist->bStopCoexDm)
+ return;
+
+ if (type == BTC_IPS_ENTER) {
+ pCoexSta->bUnderIps = true;
+
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 0);
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 0);
+ halbtc8723b1ant_SetAntPath(pBtCoexist, BTC_ANT_PATH_BT, false, true);
+ } else if (type == BTC_IPS_LEAVE) {
+ pCoexSta->bUnderIps = false;
+
+ halbtc8723b1ant_InitHwConfig(pBtCoexist, false, false);
+ halbtc8723b1ant_InitCoexDm(pBtCoexist);
+ halbtc8723b1ant_QueryBtInfo(pBtCoexist);
+ }
+}
+
+void EXhalbtc8723b1ant_LpsNotify(struct btc_coexist *pBtCoexist, u8 type)
+{
+ if (pBtCoexist->bManualControl || pBtCoexist->bStopCoexDm)
+ return;
+
+ if (type == BTC_LPS_ENABLE)
+ pCoexSta->bUnderLps = true;
+ else if (type == BTC_LPS_DISABLE)
+ pCoexSta->bUnderLps = false;
+}
+
+void EXhalbtc8723b1ant_ScanNotify(struct btc_coexist *pBtCoexist, u8 type)
+{
+ bool bWifiConnected = false, bBtHsOn = false;
+ u32 wifiLinkStatus = 0;
+ u32 numOfWifiLink = 0;
+ bool bBtCtrlAggBufSize = false;
+ u8 aggBufSize = 5;
+
+ if (pBtCoexist->bManualControl || pBtCoexist->bStopCoexDm)
+ return;
+
+ if (type == BTC_SCAN_START) {
+ pCoexSta->bWiFiIsHighPriTask = true;
+
+ halbtc8723b1ant_PsTdma(pBtCoexist, FORCE_EXEC, false, 8); /* Force antenna setup for no scan result issue */
+ pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x948);
+ pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x765);
+ pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x67);
+ } else {
+ pCoexSta->bWiFiIsHighPriTask = false;
+
+ pBtCoexist->fBtcGet(
+ pBtCoexist, BTC_GET_U1_AP_NUM, &pCoexSta->nScanAPNum
+ );
+ }
+
+ if (pBtCoexist->btInfo.bBtDisabled)
+ return;
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn);
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_CONNECTED, &bWifiConnected);
+
+ halbtc8723b1ant_QueryBtInfo(pBtCoexist);
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_LINK_STATUS, &wifiLinkStatus);
+ numOfWifiLink = wifiLinkStatus >> 16;
+
+ if (numOfWifiLink >= 2) {
+ halbtc8723b1ant_LimitedTx(pBtCoexist, NORMAL_EXEC, 0, 0, 0, 0);
+ halbtc8723b1ant_LimitedRx(
+ pBtCoexist, NORMAL_EXEC, false, bBtCtrlAggBufSize, aggBufSize
+ );
+ halbtc8723b1ant_ActionWifiMultiPort(pBtCoexist);
+ return;
+ }
+
+ if (pCoexSta->bC2hBtInquiryPage) {
+ halbtc8723b1ant_ActionBtInquiry(pBtCoexist);
+ return;
+ } else if (bBtHsOn) {
+ halbtc8723b1ant_ActionHs(pBtCoexist);
+ return;
+ }
+
+ if (type == BTC_SCAN_START) {
+ if (!bWifiConnected) /* non-connected scan */
+ halbtc8723b1ant_ActionWifiNotConnectedScan(pBtCoexist);
+ else /* wifi is connected */
+ halbtc8723b1ant_ActionWifiConnectedScan(pBtCoexist);
+ } else if (type == BTC_SCAN_FINISH) {
+ if (!bWifiConnected) /* non-connected scan */
+ halbtc8723b1ant_ActionWifiNotConnected(pBtCoexist);
+ else
+ halbtc8723b1ant_ActionWifiConnected(pBtCoexist);
+ }
+}
+
+void EXhalbtc8723b1ant_ConnectNotify(struct btc_coexist *pBtCoexist, u8 type)
+{
+ bool bWifiConnected = false, bBtHsOn = false;
+ u32 wifiLinkStatus = 0;
+ u32 numOfWifiLink = 0;
+ bool bBtCtrlAggBufSize = false;
+ u8 aggBufSize = 5;
+
+ if (
+ pBtCoexist->bManualControl ||
+ pBtCoexist->bStopCoexDm ||
+ pBtCoexist->btInfo.bBtDisabled
+ )
+ return;
+
+ if (type == BTC_ASSOCIATE_START) {
+ pCoexSta->bWiFiIsHighPriTask = true;
+ pCoexDm->nArpCnt = 0;
+ } else {
+ pCoexSta->bWiFiIsHighPriTask = false;
+ /* pCoexDm->nArpCnt = 0; */
+ }
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_LINK_STATUS, &wifiLinkStatus);
+ numOfWifiLink = wifiLinkStatus >> 16;
+ if (numOfWifiLink >= 2) {
+ halbtc8723b1ant_LimitedTx(pBtCoexist, NORMAL_EXEC, 0, 0, 0, 0);
+ halbtc8723b1ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, bBtCtrlAggBufSize, aggBufSize);
+ halbtc8723b1ant_ActionWifiMultiPort(pBtCoexist);
+ return;
+ }
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn);
+ if (pCoexSta->bC2hBtInquiryPage) {
+ halbtc8723b1ant_ActionBtInquiry(pBtCoexist);
+ return;
+ } else if (bBtHsOn) {
+ halbtc8723b1ant_ActionHs(pBtCoexist);
+ return;
+ }
+
+ if (type == BTC_ASSOCIATE_START) {
+ halbtc8723b1ant_ActionWifiNotConnectedAssoAuth(pBtCoexist);
+ } else if (type == BTC_ASSOCIATE_FINISH) {
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_CONNECTED, &bWifiConnected);
+ if (!bWifiConnected) /* non-connected scan */
+ halbtc8723b1ant_ActionWifiNotConnected(pBtCoexist);
+ else
+ halbtc8723b1ant_ActionWifiConnected(pBtCoexist);
+ }
+}
+
+void EXhalbtc8723b1ant_MediaStatusNotify(struct btc_coexist *pBtCoexist, u8 type)
+{
+ u8 H2C_Parameter[3] = {0};
+ u32 wifiBw;
+ u8 wifiCentralChnl;
+ bool bWifiUnderBMode = false;
+
+ if (
+ pBtCoexist->bManualControl ||
+ pBtCoexist->bStopCoexDm ||
+ pBtCoexist->btInfo.bBtDisabled
+ )
+ return;
+
+ if (type == BTC_MEDIA_CONNECT) {
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_UNDER_B_MODE, &bWifiUnderBMode);
+
+ /* Set CCK Tx/Rx high Pri except 11b mode */
+ if (bWifiUnderBMode) {
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x6cd, 0x00); /* CCK Tx */
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x6cf, 0x00); /* CCK Rx */
+ } else {
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x6cd, 0x10); /* CCK Tx */
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x6cf, 0x10); /* CCK Rx */
+ }
+
+ pCoexDm->backupArfrCnt1 = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x430);
+ pCoexDm->backupArfrCnt2 = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x434);
+ pCoexDm->backupRetryLimit = pBtCoexist->fBtcRead2Byte(pBtCoexist, 0x42a);
+ pCoexDm->backupAmpduMaxTime = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x456);
+ } else {
+ pCoexDm->nArpCnt = 0;
+
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x6cd, 0x0); /* CCK Tx */
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x6cf, 0x0); /* CCK Rx */
+ }
+
+ /* only 2.4G we need to inform bt the chnl mask */
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U1_WIFI_CENTRAL_CHNL, &wifiCentralChnl);
+ if ((type == BTC_MEDIA_CONNECT) && (wifiCentralChnl <= 14)) {
+ /* H2C_Parameter[0] = 0x1; */
+ H2C_Parameter[0] = 0x0;
+ H2C_Parameter[1] = wifiCentralChnl;
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
+
+ if (wifiBw == BTC_WIFI_BW_HT40)
+ H2C_Parameter[2] = 0x30;
+ else
+ H2C_Parameter[2] = 0x20;
+ }
+
+ pCoexDm->wifiChnlInfo[0] = H2C_Parameter[0];
+ pCoexDm->wifiChnlInfo[1] = H2C_Parameter[1];
+ pCoexDm->wifiChnlInfo[2] = H2C_Parameter[2];
+
+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x66, 3, H2C_Parameter);
+}
+
+void EXhalbtc8723b1ant_SpecialPacketNotify(struct btc_coexist *pBtCoexist, u8 type)
+{
+ bool bBtHsOn = false;
+ u32 wifiLinkStatus = 0;
+ u32 numOfWifiLink = 0;
+ bool bBtCtrlAggBufSize = false;
+ u8 aggBufSize = 5;
+
+ if (
+ pBtCoexist->bManualControl ||
+ pBtCoexist->bStopCoexDm ||
+ pBtCoexist->btInfo.bBtDisabled
+ )
+ return;
+
+ if (
+ type == BTC_PACKET_DHCP ||
+ type == BTC_PACKET_EAPOL ||
+ type == BTC_PACKET_ARP
+ ) {
+ if (type == BTC_PACKET_ARP) {
+ pCoexDm->nArpCnt++;
+
+ if (pCoexDm->nArpCnt >= 10) /* if APR PKT > 10 after connect, do not go to ActionWifiConnectedSpecialPacket(pBtCoexist) */
+ pCoexSta->bWiFiIsHighPriTask = false;
+ else
+ pCoexSta->bWiFiIsHighPriTask = true;
+ } else {
+ pCoexSta->bWiFiIsHighPriTask = true;
+ }
+ } else {
+ pCoexSta->bWiFiIsHighPriTask = false;
+ }
+
+ pCoexSta->specialPktPeriodCnt = 0;
+
+ pBtCoexist->fBtcGet(
+ pBtCoexist, BTC_GET_U4_WIFI_LINK_STATUS, &wifiLinkStatus
+ );
+ numOfWifiLink = wifiLinkStatus >> 16;
+
+ if (numOfWifiLink >= 2) {
+ halbtc8723b1ant_LimitedTx(pBtCoexist, NORMAL_EXEC, 0, 0, 0, 0);
+ halbtc8723b1ant_LimitedRx(
+ pBtCoexist, NORMAL_EXEC, false, bBtCtrlAggBufSize, aggBufSize
+ );
+ halbtc8723b1ant_ActionWifiMultiPort(pBtCoexist);
+ return;
+ }
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn);
+ if (pCoexSta->bC2hBtInquiryPage) {
+ halbtc8723b1ant_ActionBtInquiry(pBtCoexist);
+ return;
+ } else if (bBtHsOn) {
+ halbtc8723b1ant_ActionHs(pBtCoexist);
+ return;
+ }
+
+ if (
+ type == BTC_PACKET_DHCP ||
+ type == BTC_PACKET_EAPOL ||
+ ((type == BTC_PACKET_ARP) && (pCoexSta->bWiFiIsHighPriTask))
+ )
+ halbtc8723b1ant_ActionWifiConnectedSpecialPacket(pBtCoexist);
+}
+
+void EXhalbtc8723b1ant_BtInfoNotify(
+ struct btc_coexist *pBtCoexist, u8 *tmpBuf, u8 length
+)
+{
+ u8 btInfo = 0;
+ u8 i, rspSource = 0;
+ bool bWifiConnected = false;
+ bool bBtBusy = false;
+
+ pCoexSta->bC2hBtInfoReqSent = false;
+
+ rspSource = tmpBuf[0] & 0xf;
+ if (rspSource >= BT_INFO_SRC_8723B_1ANT_MAX)
+ rspSource = BT_INFO_SRC_8723B_1ANT_WIFI_FW;
+ pCoexSta->btInfoC2hCnt[rspSource]++;
+
+ for (i = 0; i < length; i++) {
+ pCoexSta->btInfoC2h[rspSource][i] = tmpBuf[i];
+ if (i == 1)
+ btInfo = tmpBuf[i];
+ }
+
+ if (rspSource != BT_INFO_SRC_8723B_1ANT_WIFI_FW) {
+ pCoexSta->btRetryCnt = pCoexSta->btInfoC2h[rspSource][2] & 0xf;
+
+ if (pCoexSta->btRetryCnt >= 1)
+ pCoexSta->popEventCnt++;
+
+ if (pCoexSta->btInfoC2h[rspSource][2] & 0x20)
+ pCoexSta->bC2hBtPage = true;
+ else
+ pCoexSta->bC2hBtPage = false;
+
+ pCoexSta->btRssi = pCoexSta->btInfoC2h[rspSource][3] * 2 - 90;
+ /* pCoexSta->btInfoC2h[rspSource][3]*2+10; */
+
+ pCoexSta->btInfoExt = pCoexSta->btInfoC2h[rspSource][4];
+
+ pCoexSta->bBtTxRxMask = (pCoexSta->btInfoC2h[rspSource][2] & 0x40);
+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_BL_BT_TX_RX_MASK, &pCoexSta->bBtTxRxMask);
+
+ if (!pCoexSta->bBtTxRxMask) {
+ /* BT into is responded by BT FW and BT RF REG 0x3C != 0x15 => Need to switch BT TRx Mask */
+ pBtCoexist->fBtcSetBtReg(pBtCoexist, BTC_BT_REG_RF, 0x3c, 0x15);
+ }
+
+ /* Here we need to resend some wifi info to BT */
+ /* because bt is reset and loss of the info. */
+ if (pCoexSta->btInfoExt & BIT1) {
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_CONNECTED, &bWifiConnected);
+ if (bWifiConnected)
+ EXhalbtc8723b1ant_MediaStatusNotify(pBtCoexist, BTC_MEDIA_CONNECT);
+ else
+ EXhalbtc8723b1ant_MediaStatusNotify(pBtCoexist, BTC_MEDIA_DISCONNECT);
+ }
+
+ if (pCoexSta->btInfoExt & BIT3) {
+ if (!pBtCoexist->bManualControl && !pBtCoexist->bStopCoexDm)
+ halbtc8723b1ant_IgnoreWlanAct(pBtCoexist, FORCE_EXEC, false);
+ } else {
+ /* BT already NOT ignore Wlan active, do nothing here. */
+ }
+ }
+
+ /* check BIT2 first ==> check if bt is under inquiry or page scan */
+ if (btInfo & BT_INFO_8723B_1ANT_B_INQ_PAGE)
+ pCoexSta->bC2hBtInquiryPage = true;
+ else
+ pCoexSta->bC2hBtInquiryPage = false;
+
+ /* set link exist status */
+ if (!(btInfo & BT_INFO_8723B_1ANT_B_CONNECTION)) {
+ pCoexSta->bBtLinkExist = false;
+ pCoexSta->bPanExist = false;
+ pCoexSta->bA2dpExist = false;
+ pCoexSta->bHidExist = false;
+ pCoexSta->bScoExist = false;
+ } else { /* connection exists */
+ pCoexSta->bBtLinkExist = true;
+ if (btInfo & BT_INFO_8723B_1ANT_B_FTP)
+ pCoexSta->bPanExist = true;
+ else
+ pCoexSta->bPanExist = false;
+
+ if (btInfo & BT_INFO_8723B_1ANT_B_A2DP)
+ pCoexSta->bA2dpExist = true;
+ else
+ pCoexSta->bA2dpExist = false;
+
+ if (btInfo & BT_INFO_8723B_1ANT_B_HID)
+ pCoexSta->bHidExist = true;
+ else
+ pCoexSta->bHidExist = false;
+
+ if (btInfo & BT_INFO_8723B_1ANT_B_SCO_ESCO)
+ pCoexSta->bScoExist = true;
+ else
+ pCoexSta->bScoExist = false;
+ }
+
+ halbtc8723b1ant_UpdateBtLinkInfo(pBtCoexist);
+
+ btInfo = btInfo & 0x1f; /* mask profile bit for connect-ilde identification (for CSR case: A2DP idle --> 0x41) */
+
+ if (!(btInfo & BT_INFO_8723B_1ANT_B_CONNECTION)) {
+ pCoexDm->btStatus = BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE;
+ } else if (btInfo == BT_INFO_8723B_1ANT_B_CONNECTION) {
+ /* connection exists but no busy */
+ pCoexDm->btStatus = BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE;
+ } else if (
+ (btInfo & BT_INFO_8723B_1ANT_B_SCO_ESCO) ||
+ (btInfo & BT_INFO_8723B_1ANT_B_SCO_BUSY)
+ ) {
+ pCoexDm->btStatus = BT_8723B_1ANT_BT_STATUS_SCO_BUSY;
+ } else if (btInfo & BT_INFO_8723B_1ANT_B_ACL_BUSY) {
+ if (pCoexDm->btStatus != BT_8723B_1ANT_BT_STATUS_ACL_BUSY)
+ pCoexDm->bAutoTdmaAdjust = false;
+
+ pCoexDm->btStatus = BT_8723B_1ANT_BT_STATUS_ACL_BUSY;
+ } else {
+ pCoexDm->btStatus = BT_8723B_1ANT_BT_STATUS_MAX;
+ }
+
+ if (
+ (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_BUSY) ||
+ (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_SCO_BUSY) ||
+ (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY)
+ )
+ bBtBusy = true;
+ else
+ bBtBusy = false;
+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_BL_BT_TRAFFIC_BUSY, &bBtBusy);
+
+ halbtc8723b1ant_RunCoexistMechanism(pBtCoexist);
+}
+
+void EXhalbtc8723b1ant_HaltNotify(struct btc_coexist *pBtCoexist)
+{
+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
+ halbtc8723b1ant_PsTdma(pBtCoexist, FORCE_EXEC, false, 0);
+ halbtc8723b1ant_SetAntPath(pBtCoexist, BTC_ANT_PATH_BT, false, true);
+
+ halbtc8723b1ant_IgnoreWlanAct(pBtCoexist, FORCE_EXEC, true);
+
+ EXhalbtc8723b1ant_MediaStatusNotify(pBtCoexist, BTC_MEDIA_DISCONNECT);
+
+ pBtCoexist->bStopCoexDm = true;
+}
+
+void EXhalbtc8723b1ant_PnpNotify(struct btc_coexist *pBtCoexist, u8 pnpState)
+{
+ if (pnpState == BTC_WIFI_PNP_SLEEP) {
+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 0);
+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 2);
+ halbtc8723b1ant_SetAntPath(pBtCoexist, BTC_ANT_PATH_BT, false, true);
+
+ pBtCoexist->bStopCoexDm = true;
+ } else if (pnpState == BTC_WIFI_PNP_WAKE_UP) {
+ pBtCoexist->bStopCoexDm = false;
+ halbtc8723b1ant_InitHwConfig(pBtCoexist, false, false);
+ halbtc8723b1ant_InitCoexDm(pBtCoexist);
+ halbtc8723b1ant_QueryBtInfo(pBtCoexist);
+ }
+}
+
+void EXhalbtc8723b1ant_Periodical(struct btc_coexist *pBtCoexist)
+{
+ static u8 disVerInfoCnt;
+ u32 fwVer = 0, btPatchVer = 0;
+
+ if (disVerInfoCnt <= 5) {
+ disVerInfoCnt += 1;
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_BT_PATCH_VER, &btPatchVer);
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_FW_VER, &fwVer);
+ }
+
+ halbtc8723b1ant_MonitorBtCtr(pBtCoexist);
+ halbtc8723b1ant_MonitorWiFiCtr(pBtCoexist);
+
+ if (
+ halbtc8723b1ant_IsWifiStatusChanged(pBtCoexist) ||
+ pCoexDm->bAutoTdmaAdjust
+ )
+ halbtc8723b1ant_RunCoexistMechanism(pBtCoexist);
+
+ pCoexSta->specialPktPeriodCnt++;
+}
diff --git a/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.h b/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.h
new file mode 100644
index 000000000..de471e27a
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.h
@@ -0,0 +1,184 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+/* The following is for 8723B 1ANT BT Co-exist definition */
+#define BT_INFO_8723B_1ANT_B_FTP BIT7
+#define BT_INFO_8723B_1ANT_B_A2DP BIT6
+#define BT_INFO_8723B_1ANT_B_HID BIT5
+#define BT_INFO_8723B_1ANT_B_SCO_BUSY BIT4
+#define BT_INFO_8723B_1ANT_B_ACL_BUSY BIT3
+#define BT_INFO_8723B_1ANT_B_INQ_PAGE BIT2
+#define BT_INFO_8723B_1ANT_B_SCO_ESCO BIT1
+#define BT_INFO_8723B_1ANT_B_CONNECTION BIT0
+
+#define BT_INFO_8723B_1ANT_A2DP_BASIC_RATE(_BT_INFO_EXT_) \
+ (((_BT_INFO_EXT_ & BIT0)) ? true : false)
+
+#define BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT 2
+
+#define BT_8723B_1ANT_WIFI_NOISY_THRESH 30 /* max: 255 */
+
+enum {
+ BT_INFO_SRC_8723B_1ANT_WIFI_FW = 0x0,
+ BT_INFO_SRC_8723B_1ANT_BT_RSP = 0x1,
+ BT_INFO_SRC_8723B_1ANT_BT_ACTIVE_SEND = 0x2,
+ BT_INFO_SRC_8723B_1ANT_MAX
+};
+
+enum {
+ BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE = 0x0,
+ BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE = 0x1,
+ BT_8723B_1ANT_BT_STATUS_INQ_PAGE = 0x2,
+ BT_8723B_1ANT_BT_STATUS_ACL_BUSY = 0x3,
+ BT_8723B_1ANT_BT_STATUS_SCO_BUSY = 0x4,
+ BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY = 0x5,
+ BT_8723B_1ANT_BT_STATUS_MAX
+};
+
+enum {
+ BT_8723B_1ANT_WIFI_STATUS_NON_CONNECTED_IDLE = 0x0,
+ BT_8723B_1ANT_WIFI_STATUS_NON_CONNECTED_ASSO_AUTH_SCAN = 0x1,
+ BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN = 0x2,
+ BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SPECIAL_PKT = 0x3,
+ BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE = 0x4,
+ BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY = 0x5,
+ BT_8723B_1ANT_WIFI_STATUS_MAX
+};
+
+enum {
+ BT_8723B_1ANT_COEX_ALGO_UNDEFINED = 0x0,
+ BT_8723B_1ANT_COEX_ALGO_SCO = 0x1,
+ BT_8723B_1ANT_COEX_ALGO_HID = 0x2,
+ BT_8723B_1ANT_COEX_ALGO_A2DP = 0x3,
+ BT_8723B_1ANT_COEX_ALGO_A2DP_PANHS = 0x4,
+ BT_8723B_1ANT_COEX_ALGO_PANEDR = 0x5,
+ BT_8723B_1ANT_COEX_ALGO_PANHS = 0x6,
+ BT_8723B_1ANT_COEX_ALGO_PANEDR_A2DP = 0x7,
+ BT_8723B_1ANT_COEX_ALGO_PANEDR_HID = 0x8,
+ BT_8723B_1ANT_COEX_ALGO_HID_A2DP_PANEDR = 0x9,
+ BT_8723B_1ANT_COEX_ALGO_HID_A2DP = 0xa,
+ BT_8723B_1ANT_COEX_ALGO_MAX = 0xb,
+};
+
+struct coex_dm_8723b_1ant {
+ /* fw mechanism */
+ bool bCurIgnoreWlanAct;
+ bool bPreIgnoreWlanAct;
+ u8 prePsTdma;
+ u8 curPsTdma;
+ u8 psTdmaPara[5];
+ u8 psTdmaDuAdjType;
+ bool bAutoTdmaAdjust;
+ bool bPrePsTdmaOn;
+ bool bCurPsTdmaOn;
+ bool bPreBtAutoReport;
+ bool bCurBtAutoReport;
+ u8 preLps;
+ u8 curLps;
+ u8 preRpwm;
+ u8 curRpwm;
+
+ /* sw mechanism */
+ bool bPreLowPenaltyRa;
+ bool bCurLowPenaltyRa;
+ u32 preVal0x6c0;
+ u32 curVal0x6c0;
+ u32 preVal0x6c4;
+ u32 curVal0x6c4;
+ u32 preVal0x6c8;
+ u32 curVal0x6c8;
+ u8 preVal0x6cc;
+ u8 curVal0x6cc;
+ bool bLimitedDig;
+
+ u32 backupArfrCnt1; /* Auto Rate Fallback Retry cnt */
+ u32 backupArfrCnt2; /* Auto Rate Fallback Retry cnt */
+ u16 backupRetryLimit;
+ u8 backupAmpduMaxTime;
+
+ /* algorithm related */
+ u8 preAlgorithm;
+ u8 curAlgorithm;
+ u8 btStatus;
+ u8 wifiChnlInfo[3];
+
+ u32 preRaMask;
+ u32 curRaMask;
+ u8 preArfrType;
+ u8 curArfrType;
+ u8 preRetryLimitType;
+ u8 curRetryLimitType;
+ u8 preAmpduTimeType;
+ u8 curAmpduTimeType;
+ u32 nArpCnt;
+
+ u8 errorCondition;
+};
+
+struct coex_sta_8723b_1ant {
+ bool bBtLinkExist;
+ bool bScoExist;
+ bool bA2dpExist;
+ bool bHidExist;
+ bool bPanExist;
+
+ bool bUnderLps;
+ bool bUnderIps;
+ u32 specialPktPeriodCnt;
+ u32 highPriorityTx;
+ u32 highPriorityRx;
+ u32 lowPriorityTx;
+ u32 lowPriorityRx;
+ s8 btRssi;
+ bool bBtTxRxMask;
+ u8 preBtRssiState;
+ u8 preWifiRssiState[4];
+ bool bC2hBtInfoReqSent;
+ u8 btInfoC2h[BT_INFO_SRC_8723B_1ANT_MAX][10];
+ u32 btInfoC2hCnt[BT_INFO_SRC_8723B_1ANT_MAX];
+ bool bC2hBtInquiryPage;
+ bool bC2hBtPage; /* Add for win8.1 page out issue */
+ bool bWiFiIsHighPriTask; /* Add for win8.1 page out issue */
+ u8 btRetryCnt;
+ u8 btInfoExt;
+ u32 popEventCnt;
+ u8 nScanAPNum;
+
+ u32 nCRCOK_CCK;
+ u32 nCRCOK_11g;
+ u32 nCRCOK_11n;
+ u32 nCRCOK_11nAgg;
+
+ u32 nCRCErr_CCK;
+ u32 nCRCErr_11g;
+ u32 nCRCErr_11n;
+ u32 nCRCErr_11nAgg;
+
+ bool bCCKLock;
+ bool bPreCCKLock;
+ u8 nCoexTableType;
+
+ bool bForceLpsOn;
+};
+
+/* */
+/* The following is interface which will notify coex module. */
+/* */
+void EXhalbtc8723b1ant_PowerOnSetting(struct btc_coexist *pBtCoexist);
+void EXhalbtc8723b1ant_InitHwConfig(struct btc_coexist *pBtCoexist, bool bWifiOnly);
+void EXhalbtc8723b1ant_InitCoexDm(struct btc_coexist *pBtCoexist);
+void EXhalbtc8723b1ant_IpsNotify(struct btc_coexist *pBtCoexist, u8 type);
+void EXhalbtc8723b1ant_LpsNotify(struct btc_coexist *pBtCoexist, u8 type);
+void EXhalbtc8723b1ant_ScanNotify(struct btc_coexist *pBtCoexist, u8 type);
+void EXhalbtc8723b1ant_ConnectNotify(struct btc_coexist *pBtCoexist, u8 type);
+void EXhalbtc8723b1ant_MediaStatusNotify(struct btc_coexist *pBtCoexist, u8 type);
+void EXhalbtc8723b1ant_SpecialPacketNotify(struct btc_coexist *pBtCoexist, u8 type);
+void EXhalbtc8723b1ant_BtInfoNotify(
+ struct btc_coexist *pBtCoexist, u8 *tmpBuf, u8 length
+);
+void EXhalbtc8723b1ant_HaltNotify(struct btc_coexist *pBtCoexist);
+void EXhalbtc8723b1ant_PnpNotify(struct btc_coexist *pBtCoexist, u8 pnpState);
+void EXhalbtc8723b1ant_Periodical(struct btc_coexist *pBtCoexist);
diff --git a/drivers/staging/rtl8723bs/hal/HalBtc8723b2Ant.c b/drivers/staging/rtl8723bs/hal/HalBtc8723b2Ant.c
new file mode 100644
index 000000000..c1c7b5cc1
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/HalBtc8723b2Ant.c
@@ -0,0 +1,2630 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include "Mp_Precomp.h"
+
+/* defines */
+#define HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(val) \
+do { \
+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, val); \
+ pCoexDm->psTdmaDuAdjType = val; \
+} while (0)
+
+/* Global variables, these are static variables */
+static struct coex_dm_8723b_2ant GLCoexDm8723b2Ant;
+static struct coex_dm_8723b_2ant *pCoexDm = &GLCoexDm8723b2Ant;
+static struct coex_sta_8723b_2ant GLCoexSta8723b2Ant;
+static struct coex_sta_8723b_2ant *pCoexSta = &GLCoexSta8723b2Ant;
+
+/* local function start with halbtc8723b2ant_ */
+static u8 halbtc8723b2ant_BtRssiState(
+ u8 levelNum, u8 rssiThresh, u8 rssiThresh1
+)
+{
+ s32 btRssi = 0;
+ u8 btRssiState = pCoexSta->preBtRssiState;
+
+ btRssi = pCoexSta->btRssi;
+
+ if (levelNum == 2) {
+ if (
+ (pCoexSta->preBtRssiState == BTC_RSSI_STATE_LOW) ||
+ (pCoexSta->preBtRssiState == BTC_RSSI_STATE_STAY_LOW)
+ ) {
+ if (btRssi >= (rssiThresh + BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT)) {
+ btRssiState = BTC_RSSI_STATE_HIGH;
+ } else {
+ btRssiState = BTC_RSSI_STATE_STAY_LOW;
+ }
+ } else {
+ if (btRssi < rssiThresh) {
+ btRssiState = BTC_RSSI_STATE_LOW;
+ } else {
+ btRssiState = BTC_RSSI_STATE_STAY_HIGH;
+ }
+ }
+ } else if (levelNum == 3) {
+ if (rssiThresh > rssiThresh1) {
+ return pCoexSta->preBtRssiState;
+ }
+
+ if (
+ (pCoexSta->preBtRssiState == BTC_RSSI_STATE_LOW) ||
+ (pCoexSta->preBtRssiState == BTC_RSSI_STATE_STAY_LOW)
+ ) {
+ if (btRssi >= (rssiThresh + BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT)) {
+ btRssiState = BTC_RSSI_STATE_MEDIUM;
+ } else {
+ btRssiState = BTC_RSSI_STATE_STAY_LOW;
+ }
+ } else if (
+ (pCoexSta->preBtRssiState == BTC_RSSI_STATE_MEDIUM) ||
+ (pCoexSta->preBtRssiState == BTC_RSSI_STATE_STAY_MEDIUM)
+ ) {
+ if (btRssi >= (rssiThresh1 + BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT)) {
+ btRssiState = BTC_RSSI_STATE_HIGH;
+ } else if (btRssi < rssiThresh) {
+ btRssiState = BTC_RSSI_STATE_LOW;
+ } else {
+ btRssiState = BTC_RSSI_STATE_STAY_MEDIUM;
+ }
+ } else {
+ if (btRssi < rssiThresh1) {
+ btRssiState = BTC_RSSI_STATE_MEDIUM;
+ } else {
+ btRssiState = BTC_RSSI_STATE_STAY_HIGH;
+ }
+ }
+ }
+
+ pCoexSta->preBtRssiState = btRssiState;
+
+ return btRssiState;
+}
+
+static u8 halbtc8723b2ant_WifiRssiState(
+ struct btc_coexist *pBtCoexist,
+ u8 index,
+ u8 levelNum,
+ u8 rssiThresh,
+ u8 rssiThresh1
+)
+{
+ s32 wifiRssi = 0;
+ u8 wifiRssiState = pCoexSta->preWifiRssiState[index];
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_S4_WIFI_RSSI, &wifiRssi);
+
+ if (levelNum == 2) {
+ if (
+ (pCoexSta->preWifiRssiState[index] == BTC_RSSI_STATE_LOW) ||
+ (pCoexSta->preWifiRssiState[index] == BTC_RSSI_STATE_STAY_LOW)
+ ) {
+ if (wifiRssi >= (rssiThresh + BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT)) {
+ wifiRssiState = BTC_RSSI_STATE_HIGH;
+ } else {
+ wifiRssiState = BTC_RSSI_STATE_STAY_LOW;
+ }
+ } else {
+ if (wifiRssi < rssiThresh) {
+ wifiRssiState = BTC_RSSI_STATE_LOW;
+ } else {
+ wifiRssiState = BTC_RSSI_STATE_STAY_HIGH;
+ }
+ }
+ } else if (levelNum == 3) {
+ if (rssiThresh > rssiThresh1) {
+ return pCoexSta->preWifiRssiState[index];
+ }
+
+ if (
+ (pCoexSta->preWifiRssiState[index] == BTC_RSSI_STATE_LOW) ||
+ (pCoexSta->preWifiRssiState[index] == BTC_RSSI_STATE_STAY_LOW)
+ ) {
+ if (wifiRssi >= (rssiThresh + BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT)) {
+ wifiRssiState = BTC_RSSI_STATE_MEDIUM;
+ } else {
+ wifiRssiState = BTC_RSSI_STATE_STAY_LOW;
+ }
+ } else if (
+ (pCoexSta->preWifiRssiState[index] == BTC_RSSI_STATE_MEDIUM) ||
+ (pCoexSta->preWifiRssiState[index] == BTC_RSSI_STATE_STAY_MEDIUM)
+ ) {
+ if (wifiRssi >= (rssiThresh1 + BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT)) {
+ wifiRssiState = BTC_RSSI_STATE_HIGH;
+ } else if (wifiRssi < rssiThresh) {
+ wifiRssiState = BTC_RSSI_STATE_LOW;
+ } else {
+ wifiRssiState = BTC_RSSI_STATE_STAY_MEDIUM;
+ }
+ } else {
+ if (wifiRssi < rssiThresh1) {
+ wifiRssiState = BTC_RSSI_STATE_MEDIUM;
+ } else {
+ wifiRssiState = BTC_RSSI_STATE_STAY_HIGH;
+ }
+ }
+ }
+
+ pCoexSta->preWifiRssiState[index] = wifiRssiState;
+
+ return wifiRssiState;
+}
+
+static void halbtc8723b2ant_LimitedRx(
+ struct btc_coexist *pBtCoexist,
+ bool bForceExec,
+ bool bRejApAggPkt,
+ bool bBtCtrlAggBufSize,
+ u8 aggBufSize
+)
+{
+ bool bRejectRxAgg = bRejApAggPkt;
+ bool bBtCtrlRxAggSize = bBtCtrlAggBufSize;
+ u8 rxAggSize = aggBufSize;
+
+ /* */
+ /* Rx Aggregation related setting */
+ /* */
+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_BL_TO_REJ_AP_AGG_PKT, &bRejectRxAgg);
+ /* decide BT control aggregation buf size or not */
+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_BL_BT_CTRL_AGG_SIZE, &bBtCtrlRxAggSize);
+ /* aggregation buf size, only work when BT control Rx aggregation size. */
+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_U1_AGG_BUF_SIZE, &rxAggSize);
+ /* real update aggregation setting */
+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_ACT_AGGREGATE_CTRL, NULL);
+}
+
+static void halbtc8723b2ant_QueryBtInfo(struct btc_coexist *pBtCoexist)
+{
+ u8 H2C_Parameter[1] = {0};
+
+ pCoexSta->bC2hBtInfoReqSent = true;
+
+ H2C_Parameter[0] |= BIT0; /* trigger */
+
+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x61, 1, H2C_Parameter);
+}
+
+static bool halbtc8723b2ant_IsWifiStatusChanged(struct btc_coexist *pBtCoexist)
+{
+ static bool bPreWifiBusy, bPreUnder4way, bPreBtHsOn;
+ bool bWifiBusy = false, bUnder4way = false, bBtHsOn = false;
+ bool bWifiConnected = false;
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_CONNECTED, &bWifiConnected);
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_BUSY, &bWifiBusy);
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn);
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_4_WAY_PROGRESS, &bUnder4way);
+
+ if (bWifiConnected) {
+ if (bWifiBusy != bPreWifiBusy) {
+ bPreWifiBusy = bWifiBusy;
+ return true;
+ }
+
+ if (bUnder4way != bPreUnder4way) {
+ bPreUnder4way = bUnder4way;
+ return true;
+ }
+
+ if (bBtHsOn != bPreBtHsOn) {
+ bPreBtHsOn = bBtHsOn;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static void halbtc8723b2ant_UpdateBtLinkInfo(struct btc_coexist *pBtCoexist)
+{
+ struct btc_bt_link_info *pBtLinkInfo = &pBtCoexist->btLinkInfo;
+ bool bBtHsOn = false;
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn);
+
+ pBtLinkInfo->bBtLinkExist = pCoexSta->bBtLinkExist;
+ pBtLinkInfo->bScoExist = pCoexSta->bScoExist;
+ pBtLinkInfo->bA2dpExist = pCoexSta->bA2dpExist;
+ pBtLinkInfo->bPanExist = pCoexSta->bPanExist;
+ pBtLinkInfo->bHidExist = pCoexSta->bHidExist;
+
+ /* work around for HS mode. */
+ if (bBtHsOn) {
+ pBtLinkInfo->bPanExist = true;
+ pBtLinkInfo->bBtLinkExist = true;
+ }
+
+ /* check if Sco only */
+ if (
+ pBtLinkInfo->bScoExist &&
+ !pBtLinkInfo->bA2dpExist &&
+ !pBtLinkInfo->bPanExist &&
+ !pBtLinkInfo->bHidExist
+ )
+ pBtLinkInfo->bScoOnly = true;
+ else
+ pBtLinkInfo->bScoOnly = false;
+
+ /* check if A2dp only */
+ if (
+ !pBtLinkInfo->bScoExist &&
+ pBtLinkInfo->bA2dpExist &&
+ !pBtLinkInfo->bPanExist &&
+ !pBtLinkInfo->bHidExist
+ )
+ pBtLinkInfo->bA2dpOnly = true;
+ else
+ pBtLinkInfo->bA2dpOnly = false;
+
+ /* check if Pan only */
+ if (
+ !pBtLinkInfo->bScoExist &&
+ !pBtLinkInfo->bA2dpExist &&
+ pBtLinkInfo->bPanExist &&
+ !pBtLinkInfo->bHidExist
+ )
+ pBtLinkInfo->bPanOnly = true;
+ else
+ pBtLinkInfo->bPanOnly = false;
+
+ /* check if Hid only */
+ if (
+ !pBtLinkInfo->bScoExist &&
+ !pBtLinkInfo->bA2dpExist &&
+ !pBtLinkInfo->bPanExist &&
+ pBtLinkInfo->bHidExist
+ )
+ pBtLinkInfo->bHidOnly = true;
+ else
+ pBtLinkInfo->bHidOnly = false;
+}
+
+static u8 halbtc8723b2ant_ActionAlgorithm(struct btc_coexist *pBtCoexist)
+{
+ struct btc_bt_link_info *pBtLinkInfo = &pBtCoexist->btLinkInfo;
+ bool bBtHsOn = false;
+ u8 algorithm = BT_8723B_2ANT_COEX_ALGO_UNDEFINED;
+ u8 numOfDiffProfile = 0;
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn);
+
+ if (!pBtLinkInfo->bBtLinkExist) {
+ return algorithm;
+ }
+
+ if (pBtLinkInfo->bScoExist)
+ numOfDiffProfile++;
+
+ if (pBtLinkInfo->bHidExist)
+ numOfDiffProfile++;
+
+ if (pBtLinkInfo->bPanExist)
+ numOfDiffProfile++;
+
+ if (pBtLinkInfo->bA2dpExist)
+ numOfDiffProfile++;
+
+ if (numOfDiffProfile == 1) {
+ if (pBtLinkInfo->bScoExist) {
+ algorithm = BT_8723B_2ANT_COEX_ALGO_SCO;
+ } else {
+ if (pBtLinkInfo->bHidExist) {
+ algorithm = BT_8723B_2ANT_COEX_ALGO_HID;
+ } else if (pBtLinkInfo->bA2dpExist) {
+ algorithm = BT_8723B_2ANT_COEX_ALGO_A2DP;
+ } else if (pBtLinkInfo->bPanExist) {
+ if (bBtHsOn) {
+ algorithm = BT_8723B_2ANT_COEX_ALGO_PANHS;
+ } else {
+ algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR;
+ }
+ }
+ }
+ } else if (numOfDiffProfile == 2) {
+ if (pBtLinkInfo->bScoExist) {
+ if (pBtLinkInfo->bHidExist) {
+ algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID;
+ } else if (pBtLinkInfo->bA2dpExist) {
+ algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID;
+ } else if (pBtLinkInfo->bPanExist) {
+ if (bBtHsOn) {
+ algorithm = BT_8723B_2ANT_COEX_ALGO_SCO;
+ } else {
+ algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID;
+ }
+ }
+ } else {
+ if (
+ pBtLinkInfo->bHidExist &&
+ pBtLinkInfo->bA2dpExist
+ ) {
+ algorithm = BT_8723B_2ANT_COEX_ALGO_HID_A2DP;
+ } else if (
+ pBtLinkInfo->bHidExist &&
+ pBtLinkInfo->bPanExist
+ ) {
+ if (bBtHsOn) {
+ algorithm = BT_8723B_2ANT_COEX_ALGO_HID;
+ } else {
+ algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID;
+ }
+ } else if (
+ pBtLinkInfo->bPanExist &&
+ pBtLinkInfo->bA2dpExist
+ ) {
+ if (bBtHsOn) {
+ algorithm = BT_8723B_2ANT_COEX_ALGO_A2DP_PANHS;
+ } else {
+ algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_A2DP;
+ }
+ }
+ }
+ } else if (numOfDiffProfile == 3) {
+ if (pBtLinkInfo->bScoExist) {
+ if (
+ pBtLinkInfo->bHidExist &&
+ pBtLinkInfo->bA2dpExist
+ ) {
+ algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID;
+ } else if (
+ pBtLinkInfo->bHidExist &&
+ pBtLinkInfo->bPanExist
+ ) {
+ algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID;
+ } else if (
+ pBtLinkInfo->bPanExist &&
+ pBtLinkInfo->bA2dpExist
+ ) {
+ algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID;
+ }
+ } else {
+ if (
+ pBtLinkInfo->bHidExist &&
+ pBtLinkInfo->bPanExist &&
+ pBtLinkInfo->bA2dpExist
+ ) {
+ if (bBtHsOn) {
+ algorithm = BT_8723B_2ANT_COEX_ALGO_HID_A2DP;
+ } else {
+ algorithm = BT_8723B_2ANT_COEX_ALGO_HID_A2DP_PANEDR;
+ }
+ }
+ }
+ } else if (numOfDiffProfile >= 3) {
+ if (pBtLinkInfo->bScoExist) {
+ if (
+ pBtLinkInfo->bHidExist &&
+ pBtLinkInfo->bPanExist &&
+ pBtLinkInfo->bA2dpExist
+ ) {
+ if (bBtHsOn) {
+ } else {
+ algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID;
+ }
+ }
+ }
+ }
+
+ return algorithm;
+}
+
+static void halbtc8723b2ant_SetFwDacSwingLevel(
+ struct btc_coexist *pBtCoexist, u8 dacSwingLvl
+)
+{
+ u8 H2C_Parameter[1] = {0};
+
+ /* There are several type of dacswing */
+ /* 0x18/ 0x10/ 0xc/ 0x8/ 0x4/ 0x6 */
+ H2C_Parameter[0] = dacSwingLvl;
+
+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x64, 1, H2C_Parameter);
+}
+
+static void halbtc8723b2ant_SetFwDecBtPwr(
+ struct btc_coexist *pBtCoexist, u8 decBtPwrLvl
+)
+{
+ u8 H2C_Parameter[1] = {0};
+
+ H2C_Parameter[0] = decBtPwrLvl;
+
+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x62, 1, H2C_Parameter);
+}
+
+static void halbtc8723b2ant_DecBtPwr(
+ struct btc_coexist *pBtCoexist, bool bForceExec, u8 decBtPwrLvl
+)
+{
+ pCoexDm->curBtDecPwrLvl = decBtPwrLvl;
+
+ if (!bForceExec) {
+ if (pCoexDm->preBtDecPwrLvl == pCoexDm->curBtDecPwrLvl)
+ return;
+ }
+ halbtc8723b2ant_SetFwDecBtPwr(pBtCoexist, pCoexDm->curBtDecPwrLvl);
+
+ pCoexDm->preBtDecPwrLvl = pCoexDm->curBtDecPwrLvl;
+}
+
+static void halbtc8723b2ant_FwDacSwingLvl(
+ struct btc_coexist *pBtCoexist, bool bForceExec, u8 fwDacSwingLvl
+)
+{
+ pCoexDm->curFwDacSwingLvl = fwDacSwingLvl;
+
+ if (!bForceExec) {
+ if (pCoexDm->preFwDacSwingLvl == pCoexDm->curFwDacSwingLvl)
+ return;
+ }
+
+ halbtc8723b2ant_SetFwDacSwingLevel(pBtCoexist, pCoexDm->curFwDacSwingLvl);
+
+ pCoexDm->preFwDacSwingLvl = pCoexDm->curFwDacSwingLvl;
+}
+
+static void halbtc8723b2ant_SetSwRfRxLpfCorner(
+ struct btc_coexist *pBtCoexist,
+ bool bRxRfShrinkOn
+)
+{
+ if (bRxRfShrinkOn) {
+ /* Shrink RF Rx LPF corner */
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1e, 0xfffff, 0xffffc);
+ } else {
+ /* Resume RF Rx LPF corner */
+ /* After initialized, we can use pCoexDm->btRf0x1eBackup */
+ if (pBtCoexist->bInitilized) {
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1e, 0xfffff, pCoexDm->btRf0x1eBackup);
+ }
+ }
+}
+
+static void halbtc8723b2ant_RfShrink(
+ struct btc_coexist *pBtCoexist, bool bForceExec, bool bRxRfShrinkOn
+)
+{
+ pCoexDm->bCurRfRxLpfShrink = bRxRfShrinkOn;
+
+ if (!bForceExec) {
+ if (pCoexDm->bPreRfRxLpfShrink == pCoexDm->bCurRfRxLpfShrink)
+ return;
+ }
+ halbtc8723b2ant_SetSwRfRxLpfCorner(pBtCoexist, pCoexDm->bCurRfRxLpfShrink);
+
+ pCoexDm->bPreRfRxLpfShrink = pCoexDm->bCurRfRxLpfShrink;
+}
+
+static void halbtc8723b2ant_SetSwPenaltyTxRateAdaptive(
+ struct btc_coexist *pBtCoexist, bool bLowPenaltyRa
+)
+{
+ u8 H2C_Parameter[6] = {0};
+
+ H2C_Parameter[0] = 0x6; /* opCode, 0x6 = Retry_Penalty */
+
+ if (bLowPenaltyRa) {
+ H2C_Parameter[1] |= BIT0;
+ H2C_Parameter[2] = 0x00; /* normal rate except MCS7/6/5, OFDM54/48/36 */
+ H2C_Parameter[3] = 0xf7; /* MCS7 or OFDM54 */
+ H2C_Parameter[4] = 0xf8; /* MCS6 or OFDM48 */
+ H2C_Parameter[5] = 0xf9; /* MCS5 or OFDM36 */
+ }
+
+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x69, 6, H2C_Parameter);
+}
+
+static void halbtc8723b2ant_LowPenaltyRa(
+ struct btc_coexist *pBtCoexist, bool bForceExec, bool bLowPenaltyRa
+)
+{
+ /* return; */
+ pCoexDm->bCurLowPenaltyRa = bLowPenaltyRa;
+
+ if (!bForceExec) {
+ if (pCoexDm->bPreLowPenaltyRa == pCoexDm->bCurLowPenaltyRa)
+ return;
+ }
+ halbtc8723b2ant_SetSwPenaltyTxRateAdaptive(pBtCoexist, pCoexDm->bCurLowPenaltyRa);
+
+ pCoexDm->bPreLowPenaltyRa = pCoexDm->bCurLowPenaltyRa;
+}
+
+static void halbtc8723b2ant_SetDacSwingReg(struct btc_coexist *pBtCoexist, u32 level)
+{
+ u8 val = (u8)level;
+
+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x883, 0x3e, val);
+}
+
+static void halbtc8723b2ant_SetSwFullTimeDacSwing(
+ struct btc_coexist *pBtCoexist, bool bSwDacSwingOn, u32 swDacSwingLvl
+)
+{
+ if (bSwDacSwingOn)
+ halbtc8723b2ant_SetDacSwingReg(pBtCoexist, swDacSwingLvl);
+ else
+ halbtc8723b2ant_SetDacSwingReg(pBtCoexist, 0x18);
+}
+
+
+static void halbtc8723b2ant_DacSwing(
+ struct btc_coexist *pBtCoexist,
+ bool bForceExec,
+ bool bDacSwingOn,
+ u32 dacSwingLvl
+)
+{
+ pCoexDm->bCurDacSwingOn = bDacSwingOn;
+ pCoexDm->curDacSwingLvl = dacSwingLvl;
+
+ if (!bForceExec) {
+ if ((pCoexDm->bPreDacSwingOn == pCoexDm->bCurDacSwingOn) &&
+ (pCoexDm->preDacSwingLvl == pCoexDm->curDacSwingLvl))
+ return;
+ }
+ mdelay(30);
+ halbtc8723b2ant_SetSwFullTimeDacSwing(pBtCoexist, bDacSwingOn, dacSwingLvl);
+
+ pCoexDm->bPreDacSwingOn = pCoexDm->bCurDacSwingOn;
+ pCoexDm->preDacSwingLvl = pCoexDm->curDacSwingLvl;
+}
+
+static void halbtc8723b2ant_SetAgcTable(
+ struct btc_coexist *pBtCoexist, bool bAgcTableEn
+)
+{
+ u8 rssiAdjustVal = 0;
+
+ /* BB AGC Gain Table */
+ if (bAgcTableEn) {
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0x6e1A0001);
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0x6d1B0001);
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0x6c1C0001);
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0x6b1D0001);
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0x6a1E0001);
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0x691F0001);
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0x68200001);
+ } else {
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0xaa1A0001);
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0xa91B0001);
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0xa81C0001);
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0xa71D0001);
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0xa61E0001);
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0xa51F0001);
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0xa4200001);
+ }
+
+
+ /* RF Gain */
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0xef, 0xfffff, 0x02000);
+ if (bAgcTableEn) {
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x3b, 0xfffff, 0x38fff);
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x3b, 0xfffff, 0x38ffe);
+ } else {
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x3b, 0xfffff, 0x380c3);
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x3b, 0xfffff, 0x28ce6);
+ }
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0xef, 0xfffff, 0x0);
+
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0xed, 0xfffff, 0x1);
+ if (bAgcTableEn) {
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x40, 0xfffff, 0x38fff);
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x40, 0xfffff, 0x38ffe);
+ } else {
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x40, 0xfffff, 0x380c3);
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x40, 0xfffff, 0x28ce6);
+ }
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0xed, 0xfffff, 0x0);
+
+ /* set rssiAdjustVal for wifi module. */
+ if (bAgcTableEn)
+ rssiAdjustVal = 8;
+
+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_U1_RSSI_ADJ_VAL_FOR_AGC_TABLE_ON, &rssiAdjustVal);
+}
+
+static void halbtc8723b2ant_AgcTable(
+ struct btc_coexist *pBtCoexist, bool bForceExec, bool bAgcTableEn
+)
+{
+ pCoexDm->bCurAgcTableEn = bAgcTableEn;
+
+ if (!bForceExec) {
+ if (pCoexDm->bPreAgcTableEn == pCoexDm->bCurAgcTableEn)
+ return;
+ }
+ halbtc8723b2ant_SetAgcTable(pBtCoexist, bAgcTableEn);
+
+ pCoexDm->bPreAgcTableEn = pCoexDm->bCurAgcTableEn;
+}
+
+static void halbtc8723b2ant_SetCoexTable(
+ struct btc_coexist *pBtCoexist,
+ u32 val0x6c0,
+ u32 val0x6c4,
+ u32 val0x6c8,
+ u8 val0x6cc
+)
+{
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x6c0, val0x6c0);
+
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x6c4, val0x6c4);
+
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x6c8, val0x6c8);
+
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x6cc, val0x6cc);
+}
+
+static void halbtc8723b2ant_CoexTable(
+ struct btc_coexist *pBtCoexist,
+ bool bForceExec,
+ u32 val0x6c0,
+ u32 val0x6c4,
+ u32 val0x6c8,
+ u8 val0x6cc
+)
+{
+ pCoexDm->curVal0x6c0 = val0x6c0;
+ pCoexDm->curVal0x6c4 = val0x6c4;
+ pCoexDm->curVal0x6c8 = val0x6c8;
+ pCoexDm->curVal0x6cc = val0x6cc;
+
+ if (!bForceExec) {
+ if (
+ (pCoexDm->preVal0x6c0 == pCoexDm->curVal0x6c0) &&
+ (pCoexDm->preVal0x6c4 == pCoexDm->curVal0x6c4) &&
+ (pCoexDm->preVal0x6c8 == pCoexDm->curVal0x6c8) &&
+ (pCoexDm->preVal0x6cc == pCoexDm->curVal0x6cc)
+ )
+ return;
+ }
+ halbtc8723b2ant_SetCoexTable(pBtCoexist, val0x6c0, val0x6c4, val0x6c8, val0x6cc);
+
+ pCoexDm->preVal0x6c0 = pCoexDm->curVal0x6c0;
+ pCoexDm->preVal0x6c4 = pCoexDm->curVal0x6c4;
+ pCoexDm->preVal0x6c8 = pCoexDm->curVal0x6c8;
+ pCoexDm->preVal0x6cc = pCoexDm->curVal0x6cc;
+}
+
+static void halbtc8723b2ant_CoexTableWithType(
+ struct btc_coexist *pBtCoexist, bool bForceExec, u8 type
+)
+{
+ switch (type) {
+ case 0:
+ halbtc8723b2ant_CoexTable(pBtCoexist, bForceExec, 0x55555555, 0x55555555, 0xffff, 0x3);
+ break;
+ case 1:
+ halbtc8723b2ant_CoexTable(pBtCoexist, bForceExec, 0x55555555, 0x5afa5afa, 0xffff, 0x3);
+ break;
+ case 2:
+ halbtc8723b2ant_CoexTable(pBtCoexist, bForceExec, 0x5a5a5a5a, 0x5a5a5a5a, 0xffff, 0x3);
+ break;
+ case 3:
+ halbtc8723b2ant_CoexTable(pBtCoexist, bForceExec, 0xaaaaaaaa, 0xaaaaaaaa, 0xffff, 0x3);
+ break;
+ case 4:
+ halbtc8723b2ant_CoexTable(pBtCoexist, bForceExec, 0xffffffff, 0xffffffff, 0xffff, 0x3);
+ break;
+ case 5:
+ halbtc8723b2ant_CoexTable(pBtCoexist, bForceExec, 0x5fff5fff, 0x5fff5fff, 0xffff, 0x3);
+ break;
+ case 6:
+ halbtc8723b2ant_CoexTable(pBtCoexist, bForceExec, 0x55ff55ff, 0x5a5a5a5a, 0xffff, 0x3);
+ break;
+ case 7:
+ halbtc8723b2ant_CoexTable(pBtCoexist, bForceExec, 0x55ff55ff, 0xfafafafa, 0xffff, 0x3);
+ break;
+ case 8:
+ halbtc8723b2ant_CoexTable(pBtCoexist, bForceExec, 0x5aea5aea, 0x5aea5aea, 0xffff, 0x3);
+ break;
+ case 9:
+ halbtc8723b2ant_CoexTable(pBtCoexist, bForceExec, 0x55ff55ff, 0x5aea5aea, 0xffff, 0x3);
+ break;
+ case 10:
+ halbtc8723b2ant_CoexTable(pBtCoexist, bForceExec, 0x55ff55ff, 0x5aff5aff, 0xffff, 0x3);
+ break;
+ case 11:
+ halbtc8723b2ant_CoexTable(pBtCoexist, bForceExec, 0x55ff55ff, 0x5a5f5a5f, 0xffff, 0x3);
+ break;
+ case 12:
+ halbtc8723b2ant_CoexTable(pBtCoexist, bForceExec, 0x55ff55ff, 0x5f5f5f5f, 0xffff, 0x3);
+ break;
+ default:
+ break;
+ }
+}
+
+static void halbtc8723b2ant_SetFwIgnoreWlanAct(
+ struct btc_coexist *pBtCoexist, bool bEnable
+)
+{
+ u8 H2C_Parameter[1] = {0};
+
+ if (bEnable)
+ H2C_Parameter[0] |= BIT0; /* function enable */
+
+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x63, 1, H2C_Parameter);
+}
+
+static void halbtc8723b2ant_IgnoreWlanAct(
+ struct btc_coexist *pBtCoexist, bool bForceExec, bool bEnable
+)
+{
+ pCoexDm->bCurIgnoreWlanAct = bEnable;
+
+ if (!bForceExec) {
+ if (pCoexDm->bPreIgnoreWlanAct == pCoexDm->bCurIgnoreWlanAct)
+ return;
+ }
+ halbtc8723b2ant_SetFwIgnoreWlanAct(pBtCoexist, bEnable);
+
+ pCoexDm->bPreIgnoreWlanAct = pCoexDm->bCurIgnoreWlanAct;
+}
+
+static void halbtc8723b2ant_SetFwPstdma(
+ struct btc_coexist *pBtCoexist,
+ u8 byte1,
+ u8 byte2,
+ u8 byte3,
+ u8 byte4,
+ u8 byte5
+)
+{
+ u8 H2C_Parameter[5] = {0};
+
+ H2C_Parameter[0] = byte1;
+ H2C_Parameter[1] = byte2;
+ H2C_Parameter[2] = byte3;
+ H2C_Parameter[3] = byte4;
+ H2C_Parameter[4] = byte5;
+
+ pCoexDm->psTdmaPara[0] = byte1;
+ pCoexDm->psTdmaPara[1] = byte2;
+ pCoexDm->psTdmaPara[2] = byte3;
+ pCoexDm->psTdmaPara[3] = byte4;
+ pCoexDm->psTdmaPara[4] = byte5;
+
+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x60, 5, H2C_Parameter);
+}
+
+static void halbtc8723b2ant_SwMechanism1(
+ struct btc_coexist *pBtCoexist,
+ bool bShrinkRxLPF,
+ bool bLowPenaltyRA,
+ bool bLimitedDIG,
+ bool bBTLNAConstrain
+)
+{
+ halbtc8723b2ant_RfShrink(pBtCoexist, NORMAL_EXEC, bShrinkRxLPF);
+ halbtc8723b2ant_LowPenaltyRa(pBtCoexist, NORMAL_EXEC, bLowPenaltyRA);
+}
+
+static void halbtc8723b2ant_SwMechanism2(
+ struct btc_coexist *pBtCoexist,
+ bool bAGCTableShift,
+ bool bADCBackOff,
+ bool bSWDACSwing,
+ u32 dacSwingLvl
+)
+{
+ halbtc8723b2ant_AgcTable(pBtCoexist, NORMAL_EXEC, bAGCTableShift);
+ halbtc8723b2ant_DacSwing(pBtCoexist, NORMAL_EXEC, bSWDACSwing, dacSwingLvl);
+}
+
+static void halbtc8723b2ant_SetAntPath(
+ struct btc_coexist *pBtCoexist, u8 antPosType, bool bInitHwCfg, bool bWifiOff
+)
+{
+ struct btc_board_info *pBoardInfo = &pBtCoexist->boardInfo;
+ u32 fwVer = 0, u4Tmp = 0;
+ bool bPgExtSwitch = false;
+ bool bUseExtSwitch = false;
+ u8 H2C_Parameter[2] = {0};
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_EXT_SWITCH, &bPgExtSwitch);
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_FW_VER, &fwVer); /* [31:16]=fw ver, [15:0]=fw sub ver */
+
+ if ((fwVer > 0 && fwVer < 0xc0000) || bPgExtSwitch)
+ bUseExtSwitch = true;
+
+ if (bInitHwCfg) {
+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x39, 0x8, 0x1);
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x974, 0xff);
+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x944, 0x3, 0x3);
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x930, 0x77);
+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x67, 0x20, 0x1);
+
+ if (fwVer >= 0x180000) {
+ /* Use H2C to set GNT_BT to LOW */
+ H2C_Parameter[0] = 0;
+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x6E, 1, H2C_Parameter);
+ } else {
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x765, 0x0);
+ }
+
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x0);
+
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); /* WiFi TRx Mask off */
+ pBtCoexist->fBtcSetBtReg(pBtCoexist, BTC_BT_REG_RF, 0x3c, 0x01); /* BT TRx Mask off */
+
+ if (pBoardInfo->btdmAntPos == BTC_ANTENNA_AT_MAIN_PORT) {
+ /* tell firmware "no antenna inverse" */
+ H2C_Parameter[0] = 0;
+ } else {
+ /* tell firmware "antenna inverse" */
+ H2C_Parameter[0] = 1;
+ }
+
+ if (bUseExtSwitch) {
+ /* ext switch type */
+ H2C_Parameter[1] = 1;
+ } else {
+ /* int switch type */
+ H2C_Parameter[1] = 0;
+ }
+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x65, 2, H2C_Parameter);
+ }
+
+ /* ext switch setting */
+ if (bUseExtSwitch) {
+ if (bInitHwCfg) {
+ /* 0x4c[23]= 0, 0x4c[24]= 1 Antenna control by WL/BT */
+ u4Tmp = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x4c);
+ u4Tmp &= ~BIT23;
+ u4Tmp |= BIT24;
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x4c, u4Tmp);
+ }
+
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x0); /* fixed internal switch S1->WiFi, S0->BT */
+ switch (antPosType) {
+ case BTC_ANT_WIFI_AT_MAIN:
+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x92c, 0x3, 0x1); /* ext switch main at wifi */
+ break;
+ case BTC_ANT_WIFI_AT_AUX:
+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x92c, 0x3, 0x2); /* ext switch aux at wifi */
+ break;
+ }
+ } else { /* internal switch */
+ if (bInitHwCfg) {
+ /* 0x4c[23]= 0, 0x4c[24]= 1 Antenna control by WL/BT */
+ u4Tmp = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x4c);
+ u4Tmp |= BIT23;
+ u4Tmp &= ~BIT24;
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x4c, u4Tmp);
+ }
+
+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x64, 0x1, 0x0); /* fixed external switch S1->Main, S0->Aux */
+ switch (antPosType) {
+ case BTC_ANT_WIFI_AT_MAIN:
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x0); /* fixed internal switch S1->WiFi, S0->BT */
+ break;
+ case BTC_ANT_WIFI_AT_AUX:
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x280); /* fixed internal switch S0->WiFi, S1->BT */
+ break;
+ }
+ }
+}
+
+static void halbtc8723b2ant_PsTdma(
+ struct btc_coexist *pBtCoexist, bool bForceExec, bool bTurnOn, u8 type
+)
+{
+ pCoexDm->bCurPsTdmaOn = bTurnOn;
+ pCoexDm->curPsTdma = type;
+
+ if (!bForceExec) {
+ if (
+ (pCoexDm->bPrePsTdmaOn == pCoexDm->bCurPsTdmaOn) &&
+ (pCoexDm->prePsTdma == pCoexDm->curPsTdma)
+ )
+ return;
+ }
+
+ if (bTurnOn) {
+ switch (type) {
+ case 1:
+ default:
+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x1a, 0x1a, 0xe1, 0x90);
+ break;
+ case 2:
+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x12, 0x12, 0xe1, 0x90);
+ break;
+ case 3:
+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x1c, 0x3, 0xf1, 0x90);
+ break;
+ case 4:
+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x10, 0x03, 0xf1, 0x90);
+ break;
+ case 5:
+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x1a, 0x1a, 0x60, 0x90);
+ break;
+ case 6:
+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x12, 0x12, 0x60, 0x90);
+ break;
+ case 7:
+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x1c, 0x3, 0x70, 0x90);
+ break;
+ case 8:
+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xa3, 0x10, 0x3, 0x70, 0x90);
+ break;
+ case 9:
+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x1a, 0x1a, 0xe1, 0x90);
+ break;
+ case 10:
+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x12, 0x12, 0xe1, 0x90);
+ break;
+ case 11:
+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0xa, 0xa, 0xe1, 0x90);
+ break;
+ case 12:
+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x5, 0x5, 0xe1, 0x90);
+ break;
+ case 13:
+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x1a, 0x1a, 0x60, 0x90);
+ break;
+ case 14:
+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x12, 0x12, 0x60, 0x90);
+ break;
+ case 15:
+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0xa, 0xa, 0x60, 0x90);
+ break;
+ case 16:
+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x5, 0x5, 0x60, 0x90);
+ break;
+ case 17:
+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xa3, 0x2f, 0x2f, 0x60, 0x90);
+ break;
+ case 18:
+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x5, 0x5, 0xe1, 0x90);
+ break;
+ case 19:
+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x25, 0x25, 0xe1, 0x90);
+ break;
+ case 20:
+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x25, 0x25, 0x60, 0x90);
+ break;
+ case 21:
+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x15, 0x03, 0x70, 0x90);
+ break;
+ case 71:
+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x1a, 0x1a, 0xe1, 0x90);
+ break;
+ }
+ } else {
+ /* disable PS tdma */
+ switch (type) {
+ case 0:
+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0x0, 0x0, 0x0, 0x40, 0x0);
+ break;
+ case 1:
+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0x0, 0x0, 0x0, 0x48, 0x0);
+ break;
+ default:
+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0x0, 0x0, 0x0, 0x40, 0x0);
+ break;
+ }
+ }
+
+ /* update pre state */
+ pCoexDm->bPrePsTdmaOn = pCoexDm->bCurPsTdmaOn;
+ pCoexDm->prePsTdma = pCoexDm->curPsTdma;
+}
+
+static void halbtc8723b2ant_CoexAllOff(struct btc_coexist *pBtCoexist)
+{
+ /* fw all off */
+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 1);
+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 6);
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
+
+ /* sw all off */
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
+
+ /* hw all off */
+ /* pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); */
+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 0);
+}
+
+static void halbtc8723b2ant_InitCoexDm(struct btc_coexist *pBtCoexist)
+{
+ /* force to reset coex mechanism */
+
+ halbtc8723b2ant_PsTdma(pBtCoexist, FORCE_EXEC, false, 1);
+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, FORCE_EXEC, 6);
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, FORCE_EXEC, 0);
+
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
+}
+
+static void halbtc8723b2ant_ActionBtInquiry(struct btc_coexist *pBtCoexist)
+{
+ bool bWifiConnected = false;
+ bool bLowPwrDisable = true;
+
+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_ACT_DISABLE_LOW_POWER, &bLowPwrDisable);
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_CONNECTED, &bWifiConnected);
+
+ if (bWifiConnected) {
+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 7);
+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 3);
+ } else {
+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 0);
+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 1);
+ }
+
+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, FORCE_EXEC, 6);
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
+
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
+
+ pCoexDm->bNeedRecover0x948 = true;
+ pCoexDm->backup0x948 = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x948);
+
+ halbtc8723b2ant_SetAntPath(pBtCoexist, BTC_ANT_WIFI_AT_AUX, false, false);
+}
+
+static bool halbtc8723b2ant_IsCommonAction(struct btc_coexist *pBtCoexist)
+{
+ u8 btRssiState = BTC_RSSI_STATE_HIGH;
+ bool bCommon = false, bWifiConnected = false, bWifiBusy = false;
+ bool bBtHsOn = false, bLowPwrDisable = false;
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn);
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_CONNECTED, &bWifiConnected);
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_BUSY, &bWifiBusy);
+
+ if (!bWifiConnected) {
+ bLowPwrDisable = false;
+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_ACT_DISABLE_LOW_POWER, &bLowPwrDisable);
+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
+
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 0);
+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 1);
+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 6);
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
+
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
+
+ bCommon = true;
+ } else {
+ if (BT_8723B_2ANT_BT_STATUS_NON_CONNECTED_IDLE == pCoexDm->btStatus) {
+ bLowPwrDisable = false;
+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_ACT_DISABLE_LOW_POWER, &bLowPwrDisable);
+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
+
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 0);
+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 1);
+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 0xb);
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
+
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
+
+ bCommon = true;
+ } else if (BT_8723B_2ANT_BT_STATUS_CONNECTED_IDLE == pCoexDm->btStatus) {
+ bLowPwrDisable = true;
+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_ACT_DISABLE_LOW_POWER, &bLowPwrDisable);
+
+ if (bBtHsOn)
+ return false;
+
+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
+
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 0);
+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 1);
+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 0xb);
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
+
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
+
+ bCommon = true;
+ } else {
+ bLowPwrDisable = true;
+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_ACT_DISABLE_LOW_POWER, &bLowPwrDisable);
+
+ if (bWifiBusy) {
+ bCommon = false;
+ } else {
+ if (bBtHsOn)
+ return false;
+
+ btRssiState = halbtc8723b2ant_BtRssiState(2, 29, 0);
+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
+
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 7);
+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 21);
+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 0xb);
+
+ if (BTC_RSSI_HIGH(btRssiState))
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
+
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
+ bCommon = true;
+ }
+ }
+ }
+
+ return bCommon;
+}
+
+static void halbtc8723b2ant_TdmaDurationAdjust(
+ struct btc_coexist *pBtCoexist, bool bScoHid, bool bTxPause, u8 maxInterval
+)
+{
+ static s32 up, dn, m, n, WaitCount;
+ s32 result; /* 0: no change, +1: increase WiFi duration, -1: decrease WiFi duration */
+ u8 retryCount = 0;
+
+ if (!pCoexDm->bAutoTdmaAdjust) {
+ pCoexDm->bAutoTdmaAdjust = true;
+ {
+ if (bScoHid) {
+ if (bTxPause) {
+ if (maxInterval == 1)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(13);
+ else if (maxInterval == 2)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(14);
+ else
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(15);
+ } else {
+ if (maxInterval == 1)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(9);
+ else if (maxInterval == 2)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(10);
+ else
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(11);
+ }
+ } else {
+ if (bTxPause) {
+ if (maxInterval == 1)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(5);
+ else if (maxInterval == 2)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(6);
+ else
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(7);
+ } else {
+ if (maxInterval == 1)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(1);
+ else if (maxInterval == 2)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(2);
+ else
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(3);
+ }
+ }
+ }
+ /* */
+ up = 0;
+ dn = 0;
+ m = 1;
+ n = 3;
+ result = 0;
+ WaitCount = 0;
+ } else {
+ /* acquire the BT TRx retry count from BT_Info byte2 */
+ retryCount = pCoexSta->btRetryCnt;
+ result = 0;
+ WaitCount++;
+
+ if (retryCount == 0) { /* no retry in the last 2-second duration */
+ up++;
+ dn--;
+
+ if (dn <= 0)
+ dn = 0;
+
+ if (up >= n) { /* if 連續 n 個2秒 retry count為0, 則調寬WiFi duration */
+ WaitCount = 0;
+ n = 3;
+ up = 0;
+ dn = 0;
+ result = 1;
+ }
+ } else if (retryCount <= 3) { /* <=3 retry in the last 2-second duration */
+ up--;
+ dn++;
+
+ if (up <= 0)
+ up = 0;
+
+ if (dn == 2) { /* if 連續 2 個2秒 retry count< 3, 則調窄WiFi duration */
+ if (WaitCount <= 2)
+ m++; /* 避免一直在兩個level中來回 */
+ else
+ m = 1;
+
+ if (m >= 20) /* m 最大值 = 20 ' 最大120秒 recheck是否調整 WiFi duration. */
+ m = 20;
+
+ n = 3 * m;
+ up = 0;
+ dn = 0;
+ WaitCount = 0;
+ result = -1;
+ }
+ } else { /* retry count > 3, 只要1次 retry count > 3, 則調窄WiFi duration */
+ if (WaitCount == 1)
+ m++; /* 避免一直在兩個level中來回 */
+ else
+ m = 1;
+
+ if (m >= 20) /* m 最大值 = 20 ' 最大120秒 recheck是否調整 WiFi duration. */
+ m = 20;
+
+ n = 3 * m;
+ up = 0;
+ dn = 0;
+ WaitCount = 0;
+ result = -1;
+ }
+
+ if (maxInterval == 1) {
+ if (bTxPause) {
+ if (pCoexDm->curPsTdma == 71)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(5);
+ else if (pCoexDm->curPsTdma == 1)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(5);
+ else if (pCoexDm->curPsTdma == 2)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(6);
+ else if (pCoexDm->curPsTdma == 3)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(7);
+ else if (pCoexDm->curPsTdma == 4)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(8);
+
+ if (pCoexDm->curPsTdma == 9)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(13);
+ else if (pCoexDm->curPsTdma == 10)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(14);
+ else if (pCoexDm->curPsTdma == 11)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(15);
+ else if (pCoexDm->curPsTdma == 12)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(16);
+
+ if (result == -1) {
+ if (pCoexDm->curPsTdma == 5)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(6);
+ else if (pCoexDm->curPsTdma == 6)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(7);
+ else if (pCoexDm->curPsTdma == 7)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(8);
+ else if (pCoexDm->curPsTdma == 13)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(14);
+ else if (pCoexDm->curPsTdma == 14)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(15);
+ else if (pCoexDm->curPsTdma == 15)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(16);
+ } else if (result == 1) {
+ if (pCoexDm->curPsTdma == 8)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(7);
+ else if (pCoexDm->curPsTdma == 7)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(6);
+ else if (pCoexDm->curPsTdma == 6)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(5);
+ else if (pCoexDm->curPsTdma == 16)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(15);
+ else if (pCoexDm->curPsTdma == 15)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(14);
+ else if (pCoexDm->curPsTdma == 14)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(13);
+ }
+ } else {
+ if (pCoexDm->curPsTdma == 5)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(71);
+ else if (pCoexDm->curPsTdma == 6)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(2);
+ else if (pCoexDm->curPsTdma == 7)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(3);
+ else if (pCoexDm->curPsTdma == 8)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(4);
+
+ if (pCoexDm->curPsTdma == 13)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(9);
+ else if (pCoexDm->curPsTdma == 14)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(10);
+ else if (pCoexDm->curPsTdma == 15)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(11);
+ else if (pCoexDm->curPsTdma == 16)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(12);
+
+ if (result == -1) {
+ if (pCoexDm->curPsTdma == 71)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(1);
+ else if (pCoexDm->curPsTdma == 1)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(2);
+ else if (pCoexDm->curPsTdma == 2)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(3);
+ else if (pCoexDm->curPsTdma == 3)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(4);
+ else if (pCoexDm->curPsTdma == 9)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(10);
+ else if (pCoexDm->curPsTdma == 10)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(11);
+ else if (pCoexDm->curPsTdma == 11)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(12);
+ } else if (result == 1) {
+ if (pCoexDm->curPsTdma == 4)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(3);
+ else if (pCoexDm->curPsTdma == 3)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(2);
+ else if (pCoexDm->curPsTdma == 2)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(1);
+ else if (pCoexDm->curPsTdma == 1)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(71);
+ else if (pCoexDm->curPsTdma == 12)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(11);
+ else if (pCoexDm->curPsTdma == 11)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(10);
+ else if (pCoexDm->curPsTdma == 10)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(9);
+ }
+ }
+ } else if (maxInterval == 2) {
+ if (bTxPause) {
+ if (pCoexDm->curPsTdma == 1)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(6);
+ else if (pCoexDm->curPsTdma == 2)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(6);
+ else if (pCoexDm->curPsTdma == 3)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(7);
+ else if (pCoexDm->curPsTdma == 4)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(8);
+
+ if (pCoexDm->curPsTdma == 9)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(14);
+ else if (pCoexDm->curPsTdma == 10)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(14);
+ else if (pCoexDm->curPsTdma == 11)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(15);
+ else if (pCoexDm->curPsTdma == 12)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(16);
+
+ if (result == -1) {
+ if (pCoexDm->curPsTdma == 5)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(6);
+ else if (pCoexDm->curPsTdma == 6)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(7);
+ else if (pCoexDm->curPsTdma == 7)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(8);
+ else if (pCoexDm->curPsTdma == 13)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(14);
+ else if (pCoexDm->curPsTdma == 14)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(15);
+ else if (pCoexDm->curPsTdma == 15)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(16);
+ } else if (result == 1) {
+ if (pCoexDm->curPsTdma == 8)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(7);
+ else if (pCoexDm->curPsTdma == 7)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(6);
+ else if (pCoexDm->curPsTdma == 6)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(6);
+ else if (pCoexDm->curPsTdma == 16)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(15);
+ else if (pCoexDm->curPsTdma == 15)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(14);
+ else if (pCoexDm->curPsTdma == 14)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(14);
+ }
+ } else {
+ if (pCoexDm->curPsTdma == 5)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(2);
+ else if (pCoexDm->curPsTdma == 6)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(2);
+ else if (pCoexDm->curPsTdma == 7)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(3);
+ else if (pCoexDm->curPsTdma == 8)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(4);
+
+ if (pCoexDm->curPsTdma == 13)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(10);
+ else if (pCoexDm->curPsTdma == 14)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(10);
+ else if (pCoexDm->curPsTdma == 15)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(11);
+ else if (pCoexDm->curPsTdma == 16)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(12);
+
+ if (result == -1) {
+ if (pCoexDm->curPsTdma == 1)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(2);
+ else if (pCoexDm->curPsTdma == 2)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(3);
+ else if (pCoexDm->curPsTdma == 3)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(4);
+ else if (pCoexDm->curPsTdma == 9)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(10);
+ else if (pCoexDm->curPsTdma == 10)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(11);
+ else if (pCoexDm->curPsTdma == 11)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(12);
+ } else if (result == 1) {
+ if (pCoexDm->curPsTdma == 4)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(3);
+ else if (pCoexDm->curPsTdma == 3)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(2);
+ else if (pCoexDm->curPsTdma == 2)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(2);
+ else if (pCoexDm->curPsTdma == 12)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(11);
+ else if (pCoexDm->curPsTdma == 11)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(10);
+ else if (pCoexDm->curPsTdma == 10)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(10);
+ }
+ }
+ } else if (maxInterval == 3) {
+ if (bTxPause) {
+ if (pCoexDm->curPsTdma == 1)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(7);
+ else if (pCoexDm->curPsTdma == 2)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(7);
+ else if (pCoexDm->curPsTdma == 3)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(7);
+ else if (pCoexDm->curPsTdma == 4)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(8);
+
+ if (pCoexDm->curPsTdma == 9)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(15);
+ else if (pCoexDm->curPsTdma == 10)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(15);
+ else if (pCoexDm->curPsTdma == 11)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(15);
+ else if (pCoexDm->curPsTdma == 12)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(16);
+
+ if (result == -1) {
+ if (pCoexDm->curPsTdma == 5)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(7);
+ else if (pCoexDm->curPsTdma == 6)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(7);
+ else if (pCoexDm->curPsTdma == 7)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(8);
+ else if (pCoexDm->curPsTdma == 13)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(15);
+ else if (pCoexDm->curPsTdma == 14)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(15);
+ else if (pCoexDm->curPsTdma == 15)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(16);
+ } else if (result == 1) {
+ if (pCoexDm->curPsTdma == 8)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(7);
+ else if (pCoexDm->curPsTdma == 7)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(7);
+ else if (pCoexDm->curPsTdma == 6)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(7);
+ else if (pCoexDm->curPsTdma == 16)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(15);
+ else if (pCoexDm->curPsTdma == 15)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(15);
+ else if (pCoexDm->curPsTdma == 14)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(15);
+ }
+ } else {
+ if (pCoexDm->curPsTdma == 5)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(3);
+ else if (pCoexDm->curPsTdma == 6)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(3);
+ else if (pCoexDm->curPsTdma == 7)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(3);
+ else if (pCoexDm->curPsTdma == 8)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(4);
+
+ if (pCoexDm->curPsTdma == 13)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(11);
+ else if (pCoexDm->curPsTdma == 14)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(11);
+ else if (pCoexDm->curPsTdma == 15)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(11);
+ else if (pCoexDm->curPsTdma == 16)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(12);
+
+ if (result == -1) {
+ if (pCoexDm->curPsTdma == 1)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(3);
+ else if (pCoexDm->curPsTdma == 2)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(3);
+ else if (pCoexDm->curPsTdma == 3)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(4);
+ else if (pCoexDm->curPsTdma == 9)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(11);
+ else if (pCoexDm->curPsTdma == 10)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(11);
+ else if (pCoexDm->curPsTdma == 11)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(12);
+ } else if (result == 1) {
+ if (pCoexDm->curPsTdma == 4)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(3);
+ else if (pCoexDm->curPsTdma == 3)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(3);
+ else if (pCoexDm->curPsTdma == 2)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(3);
+ else if (pCoexDm->curPsTdma == 12)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(11);
+ else if (pCoexDm->curPsTdma == 11)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(11);
+ else if (pCoexDm->curPsTdma == 10)
+ HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(11);
+ }
+ }
+ }
+ }
+
+ /* if current PsTdma not match with the recorded one (when scan, dhcp...), */
+ /* then we have to adjust it back to the previous record one. */
+ if (pCoexDm->curPsTdma != pCoexDm->psTdmaDuAdjType) {
+ bool bScan = false, bLink = false, bRoam = false;
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_SCAN, &bScan);
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_LINK, &bLink);
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_ROAM, &bRoam);
+
+ if (!bScan && !bLink && !bRoam)
+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, pCoexDm->psTdmaDuAdjType);
+
+ }
+}
+
+/* SCO only or SCO+PAN(HS) */
+static void halbtc8723b2ant_ActionSco(struct btc_coexist *pBtCoexist)
+{
+ u8 wifiRssiState, btRssiState;
+ u32 wifiBw;
+
+ wifiRssiState = halbtc8723b2ant_WifiRssiState(pBtCoexist, 0, 2, 15, 0);
+ btRssiState = halbtc8723b2ant_BtRssiState(2, 29, 0);
+
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
+
+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
+
+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 4);
+
+ if (BTC_RSSI_HIGH(btRssiState))
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
+
+ if (BTC_WIFI_BW_LEGACY == wifiBw) /* for SCO quality at 11b/g mode */
+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 2);
+ else /* for SCO quality & wifi performance balance at 11n mode */
+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 8);
+
+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 0); /* for voice quality */
+
+ /* sw mechanism */
+ if (BTC_WIFI_BW_HT40 == wifiBw) {
+ if (
+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
+ ) {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, true, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, true, 0x4);
+ } else {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, true, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, true, 0x4);
+ }
+ } else {
+ if (
+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
+ ) {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, true, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, true, 0x4);
+ } else {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, true, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, true, 0x4);
+ }
+ }
+}
+
+
+static void halbtc8723b2ant_ActionHid(struct btc_coexist *pBtCoexist)
+{
+ u8 wifiRssiState, btRssiState;
+ u32 wifiBw;
+
+ wifiRssiState = halbtc8723b2ant_WifiRssiState(pBtCoexist, 0, 2, 15, 0);
+ btRssiState = halbtc8723b2ant_BtRssiState(2, 29, 0);
+
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
+
+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
+
+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 6);
+
+ if (BTC_RSSI_HIGH(btRssiState))
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
+
+ if (BTC_WIFI_BW_LEGACY == wifiBw) /* for HID at 11b/g mode */
+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 7);
+ else /* for HID quality & wifi performance balance at 11n mode */
+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 9);
+
+ if (
+ (btRssiState == BTC_RSSI_STATE_HIGH) ||
+ (btRssiState == BTC_RSSI_STATE_STAY_HIGH)
+ )
+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 9);
+ else
+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 13);
+
+ /* sw mechanism */
+ if (BTC_WIFI_BW_HT40 == wifiBw) {
+ if (
+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
+ ) {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, true, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
+ } else {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, true, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
+ }
+ } else {
+ if (
+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
+ ) {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, true, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
+ } else {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, true, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
+ }
+ }
+}
+
+/* A2DP only / PAN(EDR) only/ A2DP+PAN(HS) */
+static void halbtc8723b2ant_ActionA2dp(struct btc_coexist *pBtCoexist)
+{
+ u8 wifiRssiState, wifiRssiState1, btRssiState;
+ u32 wifiBw;
+ u8 apNum = 0;
+
+ wifiRssiState = halbtc8723b2ant_WifiRssiState(pBtCoexist, 0, 2, 15, 0);
+ wifiRssiState1 = halbtc8723b2ant_WifiRssiState(pBtCoexist, 1, 2, 40, 0);
+ btRssiState = halbtc8723b2ant_BtRssiState(2, 29, 0);
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U1_AP_NUM, &apNum);
+
+ /* define the office environment */
+ if (apNum >= 10 && BTC_RSSI_HIGH(wifiRssiState1)) {
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 6);
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 0);
+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 1);
+
+ /* sw mechanism */
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
+ if (BTC_WIFI_BW_HT40 == wifiBw) {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, true, 0x18);
+ } else {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, true, 0x18);
+ }
+ return;
+ }
+
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
+
+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 6);
+
+ if (BTC_RSSI_HIGH(btRssiState))
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
+
+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 7);
+
+ if (
+ (btRssiState == BTC_RSSI_STATE_HIGH) ||
+ (btRssiState == BTC_RSSI_STATE_STAY_HIGH)
+ )
+ halbtc8723b2ant_TdmaDurationAdjust(pBtCoexist, false, false, 1);
+ else
+ halbtc8723b2ant_TdmaDurationAdjust(pBtCoexist, false, true, 1);
+
+ /* sw mechanism */
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
+ if (BTC_WIFI_BW_HT40 == wifiBw) {
+ if (
+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
+ ) {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
+ } else {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
+ }
+ } else {
+ if (
+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
+ ) {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
+ } else {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
+ }
+ }
+}
+
+static void halbtc8723b2ant_ActionA2dpPanHs(struct btc_coexist *pBtCoexist)
+{
+ u8 wifiRssiState, btRssiState;
+ u32 wifiBw;
+
+ wifiRssiState = halbtc8723b2ant_WifiRssiState(pBtCoexist, 0, 2, 15, 0);
+ btRssiState = halbtc8723b2ant_BtRssiState(2, 29, 0);
+
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
+
+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
+
+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 6);
+
+ if (BTC_RSSI_HIGH(btRssiState))
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
+
+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 7);
+
+ halbtc8723b2ant_TdmaDurationAdjust(pBtCoexist, false, true, 2);
+
+ /* sw mechanism */
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
+ if (BTC_WIFI_BW_HT40 == wifiBw) {
+ if (
+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
+ ) {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
+ } else {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
+ }
+ } else {
+ if (
+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
+ ) {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
+ } else {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
+ }
+ }
+}
+
+static void halbtc8723b2ant_ActionPanEdr(struct btc_coexist *pBtCoexist)
+{
+ u8 wifiRssiState, btRssiState;
+ u32 wifiBw;
+
+ wifiRssiState = halbtc8723b2ant_WifiRssiState(pBtCoexist, 0, 2, 15, 0);
+ btRssiState = halbtc8723b2ant_BtRssiState(2, 29, 0);
+
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
+
+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
+
+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 6);
+
+ if (BTC_RSSI_HIGH(btRssiState))
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
+
+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 10);
+
+ if (
+ (btRssiState == BTC_RSSI_STATE_HIGH) ||
+ (btRssiState == BTC_RSSI_STATE_STAY_HIGH)
+ )
+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 1);
+ else
+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 5);
+
+ /* sw mechanism */
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
+ if (BTC_WIFI_BW_HT40 == wifiBw) {
+ if (
+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
+ ) {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
+ } else {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
+ }
+ } else {
+ if (
+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
+ ) {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
+ } else {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
+ }
+ }
+}
+
+
+/* PAN(HS) only */
+static void halbtc8723b2ant_ActionPanHs(struct btc_coexist *pBtCoexist)
+{
+ u8 wifiRssiState, btRssiState;
+ u32 wifiBw;
+
+ wifiRssiState = halbtc8723b2ant_WifiRssiState(pBtCoexist, 0, 2, 15, 0);
+ btRssiState = halbtc8723b2ant_BtRssiState(2, 29, 0);
+
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
+
+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
+
+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 6);
+
+ if (BTC_RSSI_HIGH(btRssiState))
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
+
+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 7);
+
+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 1);
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
+ if (BTC_WIFI_BW_HT40 == wifiBw) {
+ if (
+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
+ ) {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
+ } else {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
+ }
+ } else {
+ if (
+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
+ ) {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
+ } else {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
+ }
+ }
+}
+
+/* PAN(EDR)+A2DP */
+static void halbtc8723b2ant_ActionPanEdrA2dp(struct btc_coexist *pBtCoexist)
+{
+ u8 wifiRssiState, btRssiState;
+ u32 wifiBw;
+
+ wifiRssiState = halbtc8723b2ant_WifiRssiState(pBtCoexist, 0, 2, 15, 0);
+ btRssiState = halbtc8723b2ant_BtRssiState(2, 29, 0);
+
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
+
+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
+
+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 6);
+
+ if (BTC_RSSI_HIGH(btRssiState))
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
+
+ if (
+ (btRssiState == BTC_RSSI_STATE_HIGH) ||
+ (btRssiState == BTC_RSSI_STATE_STAY_HIGH)
+ ) {
+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 12);
+ if (BTC_WIFI_BW_HT40 == wifiBw)
+ halbtc8723b2ant_TdmaDurationAdjust(pBtCoexist, false, true, 3);
+ else
+ halbtc8723b2ant_TdmaDurationAdjust(pBtCoexist, false, false, 3);
+ } else {
+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 7);
+ halbtc8723b2ant_TdmaDurationAdjust(pBtCoexist, false, true, 3);
+ }
+
+ /* sw mechanism */
+ if (BTC_WIFI_BW_HT40 == wifiBw) {
+ if (
+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
+ ) {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
+ } else {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
+ }
+ } else {
+ if (
+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
+ ) {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
+ } else {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
+ }
+ }
+}
+
+static void halbtc8723b2ant_ActionPanEdrHid(struct btc_coexist *pBtCoexist)
+{
+ u8 wifiRssiState, btRssiState;
+ u32 wifiBw;
+
+ wifiRssiState = halbtc8723b2ant_WifiRssiState(pBtCoexist, 0, 2, 15, 0);
+ btRssiState = halbtc8723b2ant_BtRssiState(2, 29, 0);
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
+
+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
+
+ if (BTC_RSSI_HIGH(btRssiState))
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
+
+ if (
+ (btRssiState == BTC_RSSI_STATE_HIGH) ||
+ (btRssiState == BTC_RSSI_STATE_STAY_HIGH)
+ ) {
+ if (BTC_WIFI_BW_HT40 == wifiBw) {
+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 3);
+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 11);
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x780);
+ } else {
+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 6);
+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 7);
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
+ }
+ halbtc8723b2ant_TdmaDurationAdjust(pBtCoexist, true, false, 2);
+ } else {
+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 6);
+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 11);
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
+ halbtc8723b2ant_TdmaDurationAdjust(pBtCoexist, true, true, 2);
+ }
+
+ /* sw mechanism */
+ if (BTC_WIFI_BW_HT40 == wifiBw) {
+ if (
+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
+ ) {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, true, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
+ } else {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, true, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
+ }
+ } else {
+ if (
+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
+ ) {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, true, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
+ } else {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, true, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
+ }
+ }
+}
+
+/* HID+A2DP+PAN(EDR) */
+static void halbtc8723b2ant_ActionHidA2dpPanEdr(struct btc_coexist *pBtCoexist)
+{
+ u8 wifiRssiState, btRssiState;
+ u32 wifiBw;
+
+ wifiRssiState = halbtc8723b2ant_WifiRssiState(pBtCoexist, 0, 2, 15, 0);
+ btRssiState = halbtc8723b2ant_BtRssiState(2, 29, 0);
+
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
+
+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
+
+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 6);
+
+ if (BTC_RSSI_HIGH(btRssiState))
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
+
+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 7);
+
+ if (
+ (btRssiState == BTC_RSSI_STATE_HIGH) ||
+ (btRssiState == BTC_RSSI_STATE_STAY_HIGH)
+ ) {
+ if (BTC_WIFI_BW_HT40 == wifiBw)
+ halbtc8723b2ant_TdmaDurationAdjust(pBtCoexist, true, true, 2);
+ else
+ halbtc8723b2ant_TdmaDurationAdjust(pBtCoexist, true, false, 3);
+ } else
+ halbtc8723b2ant_TdmaDurationAdjust(pBtCoexist, true, true, 3);
+
+ /* sw mechanism */
+ if (BTC_WIFI_BW_HT40 == wifiBw) {
+ if (
+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
+ ) {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, true, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
+ } else {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, true, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
+ }
+ } else {
+ if (
+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
+ ) {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, true, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
+ } else {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, true, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
+ }
+ }
+}
+
+static void halbtc8723b2ant_ActionHidA2dp(struct btc_coexist *pBtCoexist)
+{
+ u8 wifiRssiState, btRssiState;
+ u32 wifiBw;
+ u8 apNum = 0;
+
+ wifiRssiState = halbtc8723b2ant_WifiRssiState(pBtCoexist, 0, 2, 15, 0);
+ /* btRssiState = halbtc8723b2ant_BtRssiState(2, 29, 0); */
+ btRssiState = halbtc8723b2ant_BtRssiState(3, 29, 37);
+
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
+
+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, true, 0x5);
+
+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 6);
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
+ if (BTC_WIFI_BW_LEGACY == wifiBw) {
+ if (BTC_RSSI_HIGH(btRssiState))
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
+ else if (BTC_RSSI_MEDIUM(btRssiState))
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
+ } else {
+ /* only 802.11N mode we have to dec bt power to 4 degree */
+ if (BTC_RSSI_HIGH(btRssiState)) {
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U1_AP_NUM, &apNum);
+ /* need to check ap Number of Not */
+ if (apNum < 10)
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 4);
+ else
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
+ } else if (BTC_RSSI_MEDIUM(btRssiState))
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
+ }
+
+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 7);
+
+ if (
+ (btRssiState == BTC_RSSI_STATE_HIGH) ||
+ (btRssiState == BTC_RSSI_STATE_STAY_HIGH)
+ )
+ halbtc8723b2ant_TdmaDurationAdjust(pBtCoexist, true, false, 2);
+ else
+ halbtc8723b2ant_TdmaDurationAdjust(pBtCoexist, true, true, 2);
+
+ /* sw mechanism */
+ if (BTC_WIFI_BW_HT40 == wifiBw) {
+ if (
+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
+ ) {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, true, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
+ } else {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, true, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
+ }
+ } else {
+ if (
+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
+ ) {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, true, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
+ } else {
+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, true, false, false);
+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
+ }
+ }
+}
+
+static void halbtc8723b2ant_RunCoexistMechanism(struct btc_coexist *pBtCoexist)
+{
+ u8 algorithm = 0;
+
+ if (pBtCoexist->bManualControl) {
+ return;
+ }
+
+ if (pCoexSta->bUnderIps) {
+ return;
+ }
+
+ algorithm = halbtc8723b2ant_ActionAlgorithm(pBtCoexist);
+ if (pCoexSta->bC2hBtInquiryPage && (BT_8723B_2ANT_COEX_ALGO_PANHS != algorithm)) {
+ halbtc8723b2ant_ActionBtInquiry(pBtCoexist);
+ return;
+ } else {
+ if (pCoexDm->bNeedRecover0x948) {
+ pCoexDm->bNeedRecover0x948 = false;
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, pCoexDm->backup0x948);
+ }
+ }
+
+ pCoexDm->curAlgorithm = algorithm;
+
+ if (halbtc8723b2ant_IsCommonAction(pBtCoexist)) {
+ pCoexDm->bAutoTdmaAdjust = false;
+ } else {
+ if (pCoexDm->curAlgorithm != pCoexDm->preAlgorithm) {
+ pCoexDm->bAutoTdmaAdjust = false;
+ }
+
+
+ switch (pCoexDm->curAlgorithm) {
+ case BT_8723B_2ANT_COEX_ALGO_SCO:
+ halbtc8723b2ant_ActionSco(pBtCoexist);
+ break;
+ case BT_8723B_2ANT_COEX_ALGO_HID:
+ halbtc8723b2ant_ActionHid(pBtCoexist);
+ break;
+ case BT_8723B_2ANT_COEX_ALGO_A2DP:
+ halbtc8723b2ant_ActionA2dp(pBtCoexist);
+ break;
+ case BT_8723B_2ANT_COEX_ALGO_A2DP_PANHS:
+ halbtc8723b2ant_ActionA2dpPanHs(pBtCoexist);
+ break;
+ case BT_8723B_2ANT_COEX_ALGO_PANEDR:
+ halbtc8723b2ant_ActionPanEdr(pBtCoexist);
+ break;
+ case BT_8723B_2ANT_COEX_ALGO_PANHS:
+ halbtc8723b2ant_ActionPanHs(pBtCoexist);
+ break;
+ case BT_8723B_2ANT_COEX_ALGO_PANEDR_A2DP:
+ halbtc8723b2ant_ActionPanEdrA2dp(pBtCoexist);
+ break;
+ case BT_8723B_2ANT_COEX_ALGO_PANEDR_HID:
+ halbtc8723b2ant_ActionPanEdrHid(pBtCoexist);
+ break;
+ case BT_8723B_2ANT_COEX_ALGO_HID_A2DP_PANEDR:
+ halbtc8723b2ant_ActionHidA2dpPanEdr(pBtCoexist);
+ break;
+ case BT_8723B_2ANT_COEX_ALGO_HID_A2DP:
+ halbtc8723b2ant_ActionHidA2dp(pBtCoexist);
+ break;
+ default:
+ halbtc8723b2ant_CoexAllOff(pBtCoexist);
+ break;
+ }
+ pCoexDm->preAlgorithm = pCoexDm->curAlgorithm;
+ }
+}
+
+static void halbtc8723b2ant_WifiOffHwCfg(struct btc_coexist *pBtCoexist)
+{
+ bool bIsInMpMode = false;
+ u8 H2C_Parameter[2] = {0};
+ u32 fwVer = 0;
+
+ /* set wlan_act to low */
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x76e, 0x4);
+
+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x780); /* WiFi goto standby while GNT_BT 0-->1 */
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_FW_VER, &fwVer);
+ if (fwVer >= 0x180000) {
+ /* Use H2C to set GNT_BT to HIGH */
+ H2C_Parameter[0] = 1;
+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x6E, 1, H2C_Parameter);
+ } else
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x765, 0x18);
+
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_IS_IN_MP_MODE, &bIsInMpMode);
+ if (!bIsInMpMode)
+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x67, 0x20, 0x0); /* BT select s0/s1 is controlled by BT */
+ else
+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x67, 0x20, 0x1); /* BT select s0/s1 is controlled by WiFi */
+}
+
+static void halbtc8723b2ant_InitHwConfig(struct btc_coexist *pBtCoexist, bool bBackUp)
+{
+ u8 u1Tmp = 0;
+
+ /* backup rf 0x1e value */
+ pCoexDm->btRf0x1eBackup =
+ pBtCoexist->fBtcGetRfReg(pBtCoexist, BTC_RF_A, 0x1e, 0xfffff);
+
+ /* 0x790[5:0]= 0x5 */
+ u1Tmp = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x790);
+ u1Tmp &= 0xc0;
+ u1Tmp |= 0x5;
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x790, u1Tmp);
+
+ /* Antenna config */
+ halbtc8723b2ant_SetAntPath(pBtCoexist, BTC_ANT_WIFI_AT_MAIN, true, false);
+
+ /* PTA parameter */
+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, FORCE_EXEC, 0);
+
+ /* Enable counter statistics */
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x76e, 0xc); /* 0x76e[3] = 1, WLAN_Act control by PTA */
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x778, 0x3);
+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x40, 0x20, 0x1);
+}
+
+/* */
+/* work around function start with wa_halbtc8723b2ant_ */
+/* */
+/* */
+/* extern function start with EXhalbtc8723b2ant_ */
+/* */
+void EXhalbtc8723b2ant_PowerOnSetting(struct btc_coexist *pBtCoexist)
+{
+ struct btc_board_info *pBoardInfo = &pBtCoexist->boardInfo;
+ u8 u1Tmp = 0x4; /* Set BIT2 by default since it's 2ant case */
+ u16 u2Tmp = 0x0;
+
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x67, 0x20);
+
+ /* enable BB, REG_SYS_FUNC_EN such that we can write 0x948 correctly. */
+ u2Tmp = pBtCoexist->fBtcRead2Byte(pBtCoexist, 0x2);
+ pBtCoexist->fBtcWrite2Byte(pBtCoexist, 0x2, u2Tmp | BIT0 | BIT1);
+
+ /* set GRAN_BT = 1 */
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x765, 0x18);
+ /* set WLAN_ACT = 0 */
+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x76e, 0x4);
+
+ /* */
+ /* S0 or S1 setting and Local register setting(By the setting fw can get ant number, S0/S1, ... info) */
+ /* Local setting bit define */
+ /* BIT0: "0" for no antenna inverse; "1" for antenna inverse */
+ /* BIT1: "0" for internal switch; "1" for external switch */
+ /* BIT2: "0" for one antenna; "1" for two antenna */
+ /* NOTE: here default all internal switch and 1-antenna ==> BIT1 = 0 and BIT2 = 0 */
+ if (pBtCoexist->chipInterface == BTC_INTF_USB) {
+ /* fixed at S0 for USB interface */
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x0);
+
+ u1Tmp |= 0x1; /* antenna inverse */
+ pBtCoexist->fBtcWriteLocalReg1Byte(pBtCoexist, 0xfe08, u1Tmp);
+
+ pBoardInfo->btdmAntPos = BTC_ANTENNA_AT_AUX_PORT;
+ } else {
+ /* for PCIE and SDIO interface, we check efuse 0xc3[6] */
+ if (pBoardInfo->singleAntPath == 0) {
+ /* set to S1 */
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x280);
+ pBoardInfo->btdmAntPos = BTC_ANTENNA_AT_MAIN_PORT;
+ } else if (pBoardInfo->singleAntPath == 1) {
+ /* set to S0 */
+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x0);
+ u1Tmp |= 0x1; /* antenna inverse */
+ pBoardInfo->btdmAntPos = BTC_ANTENNA_AT_AUX_PORT;
+ }
+
+ if (pBtCoexist->chipInterface == BTC_INTF_PCI)
+ pBtCoexist->fBtcWriteLocalReg1Byte(pBtCoexist, 0x384, u1Tmp);
+ else if (pBtCoexist->chipInterface == BTC_INTF_SDIO)
+ pBtCoexist->fBtcWriteLocalReg1Byte(pBtCoexist, 0x60, u1Tmp);
+ }
+}
+
+void EXhalbtc8723b2ant_InitHwConfig(struct btc_coexist *pBtCoexist, bool bWifiOnly)
+{
+ halbtc8723b2ant_InitHwConfig(pBtCoexist, true);
+}
+
+void EXhalbtc8723b2ant_InitCoexDm(struct btc_coexist *pBtCoexist)
+{
+ halbtc8723b2ant_InitCoexDm(pBtCoexist);
+}
+
+void EXhalbtc8723b2ant_IpsNotify(struct btc_coexist *pBtCoexist, u8 type)
+{
+ if (BTC_IPS_ENTER == type) {
+ pCoexSta->bUnderIps = true;
+ halbtc8723b2ant_WifiOffHwCfg(pBtCoexist);
+ halbtc8723b2ant_IgnoreWlanAct(pBtCoexist, FORCE_EXEC, true);
+ halbtc8723b2ant_CoexAllOff(pBtCoexist);
+ } else if (BTC_IPS_LEAVE == type) {
+ pCoexSta->bUnderIps = false;
+ halbtc8723b2ant_InitHwConfig(pBtCoexist, false);
+ halbtc8723b2ant_InitCoexDm(pBtCoexist);
+ halbtc8723b2ant_QueryBtInfo(pBtCoexist);
+ }
+}
+
+void EXhalbtc8723b2ant_LpsNotify(struct btc_coexist *pBtCoexist, u8 type)
+{
+ if (BTC_LPS_ENABLE == type) {
+ pCoexSta->bUnderLps = true;
+ } else if (BTC_LPS_DISABLE == type) {
+ pCoexSta->bUnderLps = false;
+ }
+}
+
+void EXhalbtc8723b2ant_ScanNotify(struct btc_coexist *pBtCoexist, u8 type)
+{
+ if (BTC_SCAN_START == type) {
+ } else if (BTC_SCAN_FINISH == type) {
+ }
+}
+
+void EXhalbtc8723b2ant_ConnectNotify(struct btc_coexist *pBtCoexist, u8 type)
+{
+ if (BTC_ASSOCIATE_START == type) {
+ } else if (BTC_ASSOCIATE_FINISH == type) {
+ }
+}
+
+void EXhalbtc8723b2ant_MediaStatusNotify(struct btc_coexist *pBtCoexist, u8 type)
+{
+ u8 H2C_Parameter[3] = {0};
+ u32 wifiBw;
+ u8 wifiCentralChnl;
+ u8 apNum = 0;
+
+ /* only 2.4G we need to inform bt the chnl mask */
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U1_WIFI_CENTRAL_CHNL, &wifiCentralChnl);
+ if ((BTC_MEDIA_CONNECT == type) && (wifiCentralChnl <= 14)) {
+ H2C_Parameter[0] = 0x1;
+ H2C_Parameter[1] = wifiCentralChnl;
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
+ if (BTC_WIFI_BW_HT40 == wifiBw)
+ H2C_Parameter[2] = 0x30;
+ else {
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U1_AP_NUM, &apNum);
+ if (apNum < 10)
+ H2C_Parameter[2] = 0x30;
+ else
+ H2C_Parameter[2] = 0x20;
+ }
+ }
+
+ pCoexDm->wifiChnlInfo[0] = H2C_Parameter[0];
+ pCoexDm->wifiChnlInfo[1] = H2C_Parameter[1];
+ pCoexDm->wifiChnlInfo[2] = H2C_Parameter[2];
+
+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x66, 3, H2C_Parameter);
+}
+
+void EXhalbtc8723b2ant_SpecialPacketNotify(struct btc_coexist *pBtCoexist, u8 type)
+{
+}
+
+void EXhalbtc8723b2ant_BtInfoNotify(
+ struct btc_coexist *pBtCoexist, u8 *tmpBuf, u8 length
+)
+{
+ u8 btInfo = 0;
+ u8 i, rspSource = 0;
+ bool bBtBusy = false, bLimitedDig = false;
+ bool bWifiConnected = false;
+
+ pCoexSta->bC2hBtInfoReqSent = false;
+
+ rspSource = tmpBuf[0] & 0xf;
+ if (rspSource >= BT_INFO_SRC_8723B_2ANT_MAX)
+ rspSource = BT_INFO_SRC_8723B_2ANT_WIFI_FW;
+
+ pCoexSta->btInfoC2hCnt[rspSource]++;
+
+ for (i = 0; i < length; i++) {
+ pCoexSta->btInfoC2h[rspSource][i] = tmpBuf[i];
+ if (i == 1)
+ btInfo = tmpBuf[i];
+
+ }
+
+ if (pBtCoexist->bManualControl) {
+ return;
+ }
+
+ if (BT_INFO_SRC_8723B_2ANT_WIFI_FW != rspSource) {
+ pCoexSta->btRetryCnt = pCoexSta->btInfoC2h[rspSource][2] & 0xf; /* [3:0] */
+
+ pCoexSta->btRssi = pCoexSta->btInfoC2h[rspSource][3] * 2 + 10;
+
+ pCoexSta->btInfoExt = pCoexSta->btInfoC2h[rspSource][4];
+
+ pCoexSta->bBtTxRxMask = (pCoexSta->btInfoC2h[rspSource][2] & 0x40);
+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_BL_BT_TX_RX_MASK, &pCoexSta->bBtTxRxMask);
+ if (pCoexSta->bBtTxRxMask) {
+ /* BT into is responded by BT FW and BT RF REG 0x3C != 0x01 => Need to switch BT TRx Mask */
+ pBtCoexist->fBtcSetBtReg(pBtCoexist, BTC_BT_REG_RF, 0x3c, 0x01);
+ }
+
+ /* Here we need to resend some wifi info to BT */
+ /* because bt is reset and loss of the info. */
+ if ((pCoexSta->btInfoExt & BIT1)) {
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_CONNECTED, &bWifiConnected);
+
+ if (bWifiConnected)
+ EXhalbtc8723b2ant_MediaStatusNotify(pBtCoexist, BTC_MEDIA_CONNECT);
+ else
+ EXhalbtc8723b2ant_MediaStatusNotify(pBtCoexist, BTC_MEDIA_DISCONNECT);
+ }
+
+ if ((pCoexSta->btInfoExt & BIT3)) {
+ halbtc8723b2ant_IgnoreWlanAct(pBtCoexist, FORCE_EXEC, false);
+ } else {
+ /* BT already NOT ignore Wlan active, do nothing here. */
+ }
+ }
+
+ /* check BIT2 first ==> check if bt is under inquiry or page scan */
+ if (btInfo & BT_INFO_8723B_2ANT_B_INQ_PAGE)
+ pCoexSta->bC2hBtInquiryPage = true;
+ else
+ pCoexSta->bC2hBtInquiryPage = false;
+
+ /* set link exist status */
+ if (!(btInfo & BT_INFO_8723B_2ANT_B_CONNECTION)) {
+ pCoexSta->bBtLinkExist = false;
+ pCoexSta->bPanExist = false;
+ pCoexSta->bA2dpExist = false;
+ pCoexSta->bHidExist = false;
+ pCoexSta->bScoExist = false;
+ } else { /* connection exists */
+ pCoexSta->bBtLinkExist = true;
+ if (btInfo & BT_INFO_8723B_2ANT_B_FTP)
+ pCoexSta->bPanExist = true;
+ else
+ pCoexSta->bPanExist = false;
+ if (btInfo & BT_INFO_8723B_2ANT_B_A2DP)
+ pCoexSta->bA2dpExist = true;
+ else
+ pCoexSta->bA2dpExist = false;
+ if (btInfo & BT_INFO_8723B_2ANT_B_HID)
+ pCoexSta->bHidExist = true;
+ else
+ pCoexSta->bHidExist = false;
+ if (btInfo & BT_INFO_8723B_2ANT_B_SCO_ESCO)
+ pCoexSta->bScoExist = true;
+ else
+ pCoexSta->bScoExist = false;
+ }
+
+ halbtc8723b2ant_UpdateBtLinkInfo(pBtCoexist);
+
+ if (!(btInfo & BT_INFO_8723B_2ANT_B_CONNECTION)) {
+ pCoexDm->btStatus = BT_8723B_2ANT_BT_STATUS_NON_CONNECTED_IDLE;
+ } else if (btInfo == BT_INFO_8723B_2ANT_B_CONNECTION) { /* connection exists but no busy */
+ pCoexDm->btStatus = BT_8723B_2ANT_BT_STATUS_CONNECTED_IDLE;
+ } else if (
+ (btInfo & BT_INFO_8723B_2ANT_B_SCO_ESCO) ||
+ (btInfo & BT_INFO_8723B_2ANT_B_SCO_BUSY)
+ ) {
+ pCoexDm->btStatus = BT_8723B_2ANT_BT_STATUS_SCO_BUSY;
+ } else if (btInfo & BT_INFO_8723B_2ANT_B_ACL_BUSY) {
+ pCoexDm->btStatus = BT_8723B_2ANT_BT_STATUS_ACL_BUSY;
+ } else {
+ pCoexDm->btStatus = BT_8723B_2ANT_BT_STATUS_MAX;
+ }
+
+ if (
+ (BT_8723B_2ANT_BT_STATUS_ACL_BUSY == pCoexDm->btStatus) ||
+ (BT_8723B_2ANT_BT_STATUS_SCO_BUSY == pCoexDm->btStatus) ||
+ (BT_8723B_2ANT_BT_STATUS_ACL_SCO_BUSY == pCoexDm->btStatus)
+ ) {
+ bBtBusy = true;
+ bLimitedDig = true;
+ } else {
+ bBtBusy = false;
+ bLimitedDig = false;
+ }
+
+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_BL_BT_TRAFFIC_BUSY, &bBtBusy);
+
+ pCoexDm->bLimitedDig = bLimitedDig;
+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_BL_BT_LIMITED_DIG, &bLimitedDig);
+
+ halbtc8723b2ant_RunCoexistMechanism(pBtCoexist);
+}
+
+void EXhalbtc8723b2ant_HaltNotify(struct btc_coexist *pBtCoexist)
+{
+ halbtc8723b2ant_WifiOffHwCfg(pBtCoexist);
+ pBtCoexist->fBtcSetBtReg(pBtCoexist, BTC_BT_REG_RF, 0x3c, 0x15); /* BT goto standby while GNT_BT 1-->0 */
+ halbtc8723b2ant_IgnoreWlanAct(pBtCoexist, FORCE_EXEC, true);
+
+ EXhalbtc8723b2ant_MediaStatusNotify(pBtCoexist, BTC_MEDIA_DISCONNECT);
+}
+
+void EXhalbtc8723b2ant_PnpNotify(struct btc_coexist *pBtCoexist, u8 pnpState)
+{
+ if (BTC_WIFI_PNP_SLEEP == pnpState) {
+ } else if (BTC_WIFI_PNP_WAKE_UP == pnpState) {
+ halbtc8723b2ant_InitHwConfig(pBtCoexist, false);
+ halbtc8723b2ant_InitCoexDm(pBtCoexist);
+ halbtc8723b2ant_QueryBtInfo(pBtCoexist);
+ }
+}
+
+void EXhalbtc8723b2ant_Periodical(struct btc_coexist *pBtCoexist)
+{
+ static u8 disVerInfoCnt;
+ u32 fwVer = 0, btPatchVer = 0;
+
+ if (disVerInfoCnt <= 5) {
+ disVerInfoCnt += 1;
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_BT_PATCH_VER, &btPatchVer);
+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_FW_VER, &fwVer);
+ }
+
+ if (
+ halbtc8723b2ant_IsWifiStatusChanged(pBtCoexist) ||
+ pCoexDm->bAutoTdmaAdjust
+ )
+ halbtc8723b2ant_RunCoexistMechanism(pBtCoexist);
+}
diff --git a/drivers/staging/rtl8723bs/hal/HalBtc8723b2Ant.h b/drivers/staging/rtl8723bs/hal/HalBtc8723b2Ant.h
new file mode 100644
index 000000000..1896ac546
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/HalBtc8723b2Ant.h
@@ -0,0 +1,146 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+/* The following is for 8723B 2Ant BT Co-exist definition */
+#define BT_INFO_8723B_2ANT_B_FTP BIT7
+#define BT_INFO_8723B_2ANT_B_A2DP BIT6
+#define BT_INFO_8723B_2ANT_B_HID BIT5
+#define BT_INFO_8723B_2ANT_B_SCO_BUSY BIT4
+#define BT_INFO_8723B_2ANT_B_ACL_BUSY BIT3
+#define BT_INFO_8723B_2ANT_B_INQ_PAGE BIT2
+#define BT_INFO_8723B_2ANT_B_SCO_ESCO BIT1
+#define BT_INFO_8723B_2ANT_B_CONNECTION BIT0
+
+#define BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT 2
+
+enum {
+ BT_INFO_SRC_8723B_2ANT_WIFI_FW = 0x0,
+ BT_INFO_SRC_8723B_2ANT_BT_RSP = 0x1,
+ BT_INFO_SRC_8723B_2ANT_BT_ACTIVE_SEND = 0x2,
+ BT_INFO_SRC_8723B_2ANT_MAX
+};
+
+enum {
+ BT_8723B_2ANT_BT_STATUS_NON_CONNECTED_IDLE = 0x0,
+ BT_8723B_2ANT_BT_STATUS_CONNECTED_IDLE = 0x1,
+ BT_8723B_2ANT_BT_STATUS_INQ_PAGE = 0x2,
+ BT_8723B_2ANT_BT_STATUS_ACL_BUSY = 0x3,
+ BT_8723B_2ANT_BT_STATUS_SCO_BUSY = 0x4,
+ BT_8723B_2ANT_BT_STATUS_ACL_SCO_BUSY = 0x5,
+ BT_8723B_2ANT_BT_STATUS_MAX
+};
+
+enum {
+ BT_8723B_2ANT_COEX_ALGO_UNDEFINED = 0x0,
+ BT_8723B_2ANT_COEX_ALGO_SCO = 0x1,
+ BT_8723B_2ANT_COEX_ALGO_HID = 0x2,
+ BT_8723B_2ANT_COEX_ALGO_A2DP = 0x3,
+ BT_8723B_2ANT_COEX_ALGO_A2DP_PANHS = 0x4,
+ BT_8723B_2ANT_COEX_ALGO_PANEDR = 0x5,
+ BT_8723B_2ANT_COEX_ALGO_PANHS = 0x6,
+ BT_8723B_2ANT_COEX_ALGO_PANEDR_A2DP = 0x7,
+ BT_8723B_2ANT_COEX_ALGO_PANEDR_HID = 0x8,
+ BT_8723B_2ANT_COEX_ALGO_HID_A2DP_PANEDR = 0x9,
+ BT_8723B_2ANT_COEX_ALGO_HID_A2DP = 0xa,
+ BT_8723B_2ANT_COEX_ALGO_MAX = 0xb,
+};
+
+struct coex_dm_8723b_2ant {
+ /* fw mechanism */
+ u8 preBtDecPwrLvl;
+ u8 curBtDecPwrLvl;
+ u8 preFwDacSwingLvl;
+ u8 curFwDacSwingLvl;
+ bool bCurIgnoreWlanAct;
+ bool bPreIgnoreWlanAct;
+ u8 prePsTdma;
+ u8 curPsTdma;
+ u8 psTdmaPara[5];
+ u8 psTdmaDuAdjType;
+ bool bResetTdmaAdjust;
+ bool bAutoTdmaAdjust;
+ bool bPrePsTdmaOn;
+ bool bCurPsTdmaOn;
+ bool bPreBtAutoReport;
+ bool bCurBtAutoReport;
+
+ /* sw mechanism */
+ bool bPreRfRxLpfShrink;
+ bool bCurRfRxLpfShrink;
+ u32 btRf0x1eBackup;
+ bool bPreLowPenaltyRa;
+ bool bCurLowPenaltyRa;
+ bool bPreDacSwingOn;
+ u32 preDacSwingLvl;
+ bool bCurDacSwingOn;
+ u32 curDacSwingLvl;
+ bool bPreAdcBackOff;
+ bool bCurAdcBackOff;
+ bool bPreAgcTableEn;
+ bool bCurAgcTableEn;
+ u32 preVal0x6c0;
+ u32 curVal0x6c0;
+ u32 preVal0x6c4;
+ u32 curVal0x6c4;
+ u32 preVal0x6c8;
+ u32 curVal0x6c8;
+ u8 preVal0x6cc;
+ u8 curVal0x6cc;
+ bool bLimitedDig;
+
+ /* algorithm related */
+ u8 preAlgorithm;
+ u8 curAlgorithm;
+ u8 btStatus;
+ u8 wifiChnlInfo[3];
+
+ bool bNeedRecover0x948;
+ u32 backup0x948;
+};
+
+struct coex_sta_8723b_2ant {
+ bool bBtLinkExist;
+ bool bScoExist;
+ bool bA2dpExist;
+ bool bHidExist;
+ bool bPanExist;
+
+ bool bUnderLps;
+ bool bUnderIps;
+ u32 highPriorityTx;
+ u32 highPriorityRx;
+ u32 lowPriorityTx;
+ u32 lowPriorityRx;
+ u8 btRssi;
+ bool bBtTxRxMask;
+ u8 preBtRssiState;
+ u8 preWifiRssiState[4];
+ bool bC2hBtInfoReqSent;
+ u8 btInfoC2h[BT_INFO_SRC_8723B_2ANT_MAX][10];
+ u32 btInfoC2hCnt[BT_INFO_SRC_8723B_2ANT_MAX];
+ bool bC2hBtInquiryPage;
+ u8 btRetryCnt;
+ u8 btInfoExt;
+};
+
+/* */
+/* The following is interface which will notify coex module. */
+/* */
+void EXhalbtc8723b2ant_PowerOnSetting(struct btc_coexist *pBtCoexist);
+void EXhalbtc8723b2ant_InitHwConfig(struct btc_coexist *pBtCoexist, bool bWifiOnly);
+void EXhalbtc8723b2ant_InitCoexDm(struct btc_coexist *pBtCoexist);
+void EXhalbtc8723b2ant_IpsNotify(struct btc_coexist *pBtCoexist, u8 type);
+void EXhalbtc8723b2ant_LpsNotify(struct btc_coexist *pBtCoexist, u8 type);
+void EXhalbtc8723b2ant_ScanNotify(struct btc_coexist *pBtCoexist, u8 type);
+void EXhalbtc8723b2ant_ConnectNotify(struct btc_coexist *pBtCoexist, u8 type);
+void EXhalbtc8723b2ant_MediaStatusNotify(struct btc_coexist *pBtCoexist, u8 type);
+void EXhalbtc8723b2ant_SpecialPacketNotify(struct btc_coexist *pBtCoexist, u8 type);
+void EXhalbtc8723b2ant_BtInfoNotify(
+ struct btc_coexist *pBtCoexist, u8 *tmpBuf, u8 length
+);
+void EXhalbtc8723b2ant_HaltNotify(struct btc_coexist *pBtCoexist);
+void EXhalbtc8723b2ant_PnpNotify(struct btc_coexist *pBtCoexist, u8 pnpState);
+void EXhalbtc8723b2ant_Periodical(struct btc_coexist *pBtCoexist);
diff --git a/drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h b/drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h
new file mode 100644
index 000000000..9091f2f75
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h
@@ -0,0 +1,426 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __HALBTC_OUT_SRC_H__
+#define __HALBTC_OUT_SRC_H__
+
+#define NORMAL_EXEC false
+#define FORCE_EXEC true
+
+#define BTC_RF_OFF 0x0
+#define BTC_RF_ON 0x1
+
+#define BTC_RF_A 0x0
+#define BTC_RF_B 0x1
+#define BTC_RF_C 0x2
+#define BTC_RF_D 0x3
+
+#define BTC_SMSP SINGLEMAC_SINGLEPHY
+#define BTC_DMDP DUALMAC_DUALPHY
+#define BTC_DMSP DUALMAC_SINGLEPHY
+#define BTC_MP_UNKNOWN 0xff
+
+#define BT_COEX_ANT_TYPE_PG 0
+#define BT_COEX_ANT_TYPE_ANTDIV 1
+#define BT_COEX_ANT_TYPE_DETECTED 2
+
+#define BTC_MIMO_PS_STATIC 0 /* 1ss */
+#define BTC_MIMO_PS_DYNAMIC 1 /* 2ss */
+
+#define BTC_RATE_DISABLE 0
+#define BTC_RATE_ENABLE 1
+
+/* single Antenna definition */
+#define BTC_ANT_PATH_WIFI 0
+#define BTC_ANT_PATH_BT 1
+#define BTC_ANT_PATH_PTA 2
+/* dual Antenna definition */
+#define BTC_ANT_WIFI_AT_MAIN 0
+#define BTC_ANT_WIFI_AT_AUX 1
+/* coupler Antenna definition */
+#define BTC_ANT_WIFI_AT_CPL_MAIN 0
+#define BTC_ANT_WIFI_AT_CPL_AUX 1
+
+enum {
+ BTC_PS_WIFI_NATIVE = 0, /* wifi original power save behavior */
+ BTC_PS_LPS_ON = 1,
+ BTC_PS_LPS_OFF = 2,
+ BTC_PS_MAX
+};
+
+enum {
+ BTC_BT_REG_RF = 0,
+ BTC_BT_REG_MODEM = 1,
+ BTC_BT_REG_BLUEWIZE = 2,
+ BTC_BT_REG_VENDOR = 3,
+ BTC_BT_REG_LE = 4,
+ BTC_BT_REG_MAX
+};
+
+enum btc_chip_interface {
+ BTC_INTF_UNKNOWN = 0,
+ BTC_INTF_PCI = 1,
+ BTC_INTF_USB = 2,
+ BTC_INTF_SDIO = 3,
+ BTC_INTF_MAX
+};
+
+/* following is for wifi link status */
+#define WIFI_STA_CONNECTED BIT0
+#define WIFI_AP_CONNECTED BIT1
+#define WIFI_HS_CONNECTED BIT2
+#define WIFI_P2P_GO_CONNECTED BIT3
+#define WIFI_P2P_GC_CONNECTED BIT4
+
+struct btc_board_info {
+ /* The following is some board information */
+ u8 pgAntNum; /* pg ant number */
+ u8 btdmAntNum; /* ant number for btdm */
+ u8 btdmAntPos; /* Bryant Add to indicate Antenna Position for (pgAntNum = 2) && (btdmAntNum = 1) (DPDT+1Ant case) */
+ u8 singleAntPath; /* current used for 8723b only, 1 =>s0, 0 =>s1 */
+ /* bool bBtExist; */
+};
+
+enum {
+ BTC_RSSI_STATE_HIGH = 0x0,
+ BTC_RSSI_STATE_MEDIUM = 0x1,
+ BTC_RSSI_STATE_LOW = 0x2,
+ BTC_RSSI_STATE_STAY_HIGH = 0x3,
+ BTC_RSSI_STATE_STAY_MEDIUM = 0x4,
+ BTC_RSSI_STATE_STAY_LOW = 0x5,
+ BTC_RSSI_MAX
+};
+#define BTC_RSSI_HIGH(_rssi_) ((_rssi_ == BTC_RSSI_STATE_HIGH || _rssi_ == BTC_RSSI_STATE_STAY_HIGH) ? true : false)
+#define BTC_RSSI_MEDIUM(_rssi_) ((_rssi_ == BTC_RSSI_STATE_MEDIUM || _rssi_ == BTC_RSSI_STATE_STAY_MEDIUM) ? true : false)
+#define BTC_RSSI_LOW(_rssi_) ((_rssi_ == BTC_RSSI_STATE_LOW || _rssi_ == BTC_RSSI_STATE_STAY_LOW) ? true : false)
+
+enum {
+ BTC_WIFI_BW_LEGACY = 0x0,
+ BTC_WIFI_BW_HT20 = 0x1,
+ BTC_WIFI_BW_HT40 = 0x2,
+ BTC_WIFI_BW_MAX
+};
+
+enum {
+ BTC_WIFI_TRAFFIC_TX = 0x0,
+ BTC_WIFI_TRAFFIC_RX = 0x1,
+ BTC_WIFI_TRAFFIC_MAX
+};
+
+enum {
+ BTC_WIFI_PNP_WAKE_UP = 0x0,
+ BTC_WIFI_PNP_SLEEP = 0x1,
+ BTC_WIFI_PNP_MAX
+};
+
+/* defined for BFP_BTC_GET */
+enum {
+ /* type bool */
+ BTC_GET_BL_HS_OPERATION,
+ BTC_GET_BL_HS_CONNECTING,
+ BTC_GET_BL_WIFI_CONNECTED,
+ BTC_GET_BL_WIFI_BUSY,
+ BTC_GET_BL_WIFI_SCAN,
+ BTC_GET_BL_WIFI_LINK,
+ BTC_GET_BL_WIFI_ROAM,
+ BTC_GET_BL_WIFI_4_WAY_PROGRESS,
+ BTC_GET_BL_WIFI_AP_MODE_ENABLE,
+ BTC_GET_BL_WIFI_ENABLE_ENCRYPTION,
+ BTC_GET_BL_WIFI_UNDER_B_MODE,
+ BTC_GET_BL_EXT_SWITCH,
+ BTC_GET_BL_WIFI_IS_IN_MP_MODE,
+
+ /* type s32 */
+ BTC_GET_S4_WIFI_RSSI,
+ BTC_GET_S4_HS_RSSI,
+
+ /* type u32 */
+ BTC_GET_U4_WIFI_BW,
+ BTC_GET_U4_WIFI_TRAFFIC_DIRECTION,
+ BTC_GET_U4_WIFI_FW_VER,
+ BTC_GET_U4_WIFI_LINK_STATUS,
+ BTC_GET_U4_BT_PATCH_VER,
+
+ /* type u8 */
+ BTC_GET_U1_WIFI_DOT11_CHNL,
+ BTC_GET_U1_WIFI_CENTRAL_CHNL,
+ BTC_GET_U1_WIFI_HS_CHNL,
+ BTC_GET_U1_MAC_PHY_MODE,
+ BTC_GET_U1_AP_NUM,
+
+ /* for 1Ant ====== */
+ BTC_GET_U1_LPS_MODE,
+
+ BTC_GET_MAX
+};
+
+/* defined for BFP_BTC_SET */
+enum {
+ /* type bool */
+ BTC_SET_BL_BT_DISABLE,
+ BTC_SET_BL_BT_TRAFFIC_BUSY,
+ BTC_SET_BL_BT_LIMITED_DIG,
+ BTC_SET_BL_FORCE_TO_ROAM,
+ BTC_SET_BL_TO_REJ_AP_AGG_PKT,
+ BTC_SET_BL_BT_CTRL_AGG_SIZE,
+ BTC_SET_BL_INC_SCAN_DEV_NUM,
+ BTC_SET_BL_BT_TX_RX_MASK,
+
+ /* type u8 */
+ BTC_SET_U1_RSSI_ADJ_VAL_FOR_AGC_TABLE_ON,
+ BTC_SET_U1_AGG_BUF_SIZE,
+
+ /* type trigger some action */
+ BTC_SET_ACT_GET_BT_RSSI,
+ BTC_SET_ACT_AGGREGATE_CTRL,
+ /* for 1Ant ====== */
+ /* type bool */
+
+ /* type u8 */
+ BTC_SET_U1_RSSI_ADJ_VAL_FOR_1ANT_COEX_TYPE,
+ BTC_SET_U1_LPS_VAL,
+ BTC_SET_U1_RPWM_VAL,
+ /* type trigger some action */
+ BTC_SET_ACT_LEAVE_LPS,
+ BTC_SET_ACT_ENTER_LPS,
+ BTC_SET_ACT_NORMAL_LPS,
+ BTC_SET_ACT_DISABLE_LOW_POWER,
+ BTC_SET_ACT_UPDATE_RAMASK,
+ BTC_SET_ACT_SEND_MIMO_PS,
+ /* BT Coex related */
+ BTC_SET_ACT_CTRL_BT_INFO,
+ BTC_SET_ACT_CTRL_BT_COEX,
+ BTC_SET_ACT_CTRL_8723B_ANT,
+ /* */
+ BTC_SET_MAX
+};
+
+enum {
+ BTC_DBG_DISP_COEX_STATISTICS = 0x0,
+ BTC_DBG_DISP_BT_LINK_INFO = 0x1,
+ BTC_DBG_DISP_FW_PWR_MODE_CMD = 0x2,
+ BTC_DBG_DISP_MAX
+};
+
+enum {
+ BTC_IPS_LEAVE = 0x0,
+ BTC_IPS_ENTER = 0x1,
+ BTC_IPS_MAX
+};
+
+enum {
+ BTC_LPS_DISABLE = 0x0,
+ BTC_LPS_ENABLE = 0x1,
+ BTC_LPS_MAX
+};
+
+enum {
+ BTC_SCAN_FINISH = 0x0,
+ BTC_SCAN_START = 0x1,
+ BTC_SCAN_MAX
+};
+
+enum {
+ BTC_ASSOCIATE_FINISH = 0x0,
+ BTC_ASSOCIATE_START = 0x1,
+ BTC_ASSOCIATE_MAX
+};
+
+enum {
+ BTC_MEDIA_DISCONNECT = 0x0,
+ BTC_MEDIA_CONNECT = 0x1,
+ BTC_MEDIA_MAX
+};
+
+enum {
+ BTC_PACKET_UNKNOWN = 0x0,
+ BTC_PACKET_DHCP = 0x1,
+ BTC_PACKET_ARP = 0x2,
+ BTC_PACKET_EAPOL = 0x3,
+ BTC_PACKET_MAX
+};
+
+/* Bryant Add */
+enum {
+ BTC_ANTENNA_AT_MAIN_PORT = 0x1,
+ BTC_ANTENNA_AT_AUX_PORT = 0x2,
+};
+
+typedef u8 (*BFP_BTC_R1)(void *pBtcContext, u32 RegAddr);
+typedef u16(*BFP_BTC_R2)(void *pBtcContext, u32 RegAddr);
+typedef u32 (*BFP_BTC_R4)(void *pBtcContext, u32 RegAddr);
+typedef void (*BFP_BTC_W1)(void *pBtcContext, u32 RegAddr, u8 Data);
+typedef void(*BFP_BTC_W1_BIT_MASK)(
+ void *pBtcContext, u32 regAddr, u8 bitMask, u8 data1b
+);
+typedef void (*BFP_BTC_W2)(void *pBtcContext, u32 RegAddr, u16 Data);
+typedef void (*BFP_BTC_W4)(void *pBtcContext, u32 RegAddr, u32 Data);
+typedef void (*BFP_BTC_LOCAL_REG_W1)(void *pBtcContext, u32 RegAddr, u8 Data);
+typedef void (*BFP_BTC_SET_BB_REG)(
+ void *pBtcContext, u32 RegAddr, u32 BitMask, u32 Data
+);
+typedef u32 (*BFP_BTC_GET_BB_REG)(void *pBtcContext, u32 RegAddr, u32 BitMask);
+typedef void (*BFP_BTC_SET_RF_REG)(
+ void *pBtcContext, u8 eRFPath, u32 RegAddr, u32 BitMask, u32 Data
+);
+typedef u32 (*BFP_BTC_GET_RF_REG)(
+ void *pBtcContext, u8 eRFPath, u32 RegAddr, u32 BitMask
+);
+typedef void (*BFP_BTC_FILL_H2C)(
+ void *pBtcContext, u8 elementId, u32 cmdLen, u8 *pCmdBuffer
+);
+
+typedef u8 (*BFP_BTC_GET)(void *pBtCoexist, u8 getType, void *pOutBuf);
+
+typedef u8 (*BFP_BTC_SET)(void *pBtCoexist, u8 setType, void *pInBuf);
+typedef void (*BFP_BTC_SET_BT_REG)(
+ void *pBtcContext, u8 regType, u32 offset, u32 value
+);
+typedef u32 (*BFP_BTC_GET_BT_REG)(void *pBtcContext, u8 regType, u32 offset);
+typedef void (*BFP_BTC_DISP_DBG_MSG)(void *pBtCoexist, u8 dispType);
+
+struct btc_bt_info {
+ bool bBtDisabled;
+ u8 rssiAdjustForAgcTableOn;
+ u8 rssiAdjustFor1AntCoexType;
+ bool bPreBtCtrlAggBufSize;
+ bool bBtCtrlAggBufSize;
+ bool bRejectAggPkt;
+ bool bIncreaseScanDevNum;
+ bool bBtTxRxMask;
+ u8 preAggBufSize;
+ u8 aggBufSize;
+ bool bBtBusy;
+ bool bLimitedDig;
+ u16 btHciVer;
+ u16 btRealFwVer;
+ u8 btFwVer;
+ u32 getBtFwVerCnt;
+
+ bool bBtDisableLowPwr;
+
+ bool bBtCtrlLps;
+ bool bBtLpsOn;
+ bool bForceToRoam; /* for 1Ant solution */
+ u8 lpsVal;
+ u8 rpwmVal;
+ u32 raMask;
+};
+
+struct btc_stack_info {
+ bool bProfileNotified;
+ u16 hciVersion; /* stack hci version */
+ u8 numOfLink;
+ bool bBtLinkExist;
+ bool bScoExist;
+ bool bAclExist;
+ bool bA2dpExist;
+ bool bHidExist;
+ u8 numOfHid;
+ bool bPanExist;
+ bool bUnknownAclExist;
+ s8 minBtRssi;
+};
+
+struct btc_bt_link_info {
+ bool bBtLinkExist;
+ bool bScoExist;
+ bool bScoOnly;
+ bool bA2dpExist;
+ bool bA2dpOnly;
+ bool bHidExist;
+ bool bHidOnly;
+ bool bPanExist;
+ bool bPanOnly;
+ bool bSlaveRole;
+};
+
+struct btc_statistics {
+ u32 cntBind;
+ u32 cntPowerOn;
+ u32 cntInitHwConfig;
+ u32 cntInitCoexDm;
+ u32 cntIpsNotify;
+ u32 cntLpsNotify;
+ u32 cntScanNotify;
+ u32 cntConnectNotify;
+ u32 cntMediaStatusNotify;
+ u32 cntSpecialPacketNotify;
+ u32 cntBtInfoNotify;
+ u32 cntRfStatusNotify;
+ u32 cntPeriodical;
+ u32 cntCoexDmSwitch;
+ u32 cntStackOperationNotify;
+ u32 cntDbgCtrl;
+};
+
+struct btc_coexist {
+ bool bBinded; /* make sure only one adapter can bind the data context */
+ void *Adapter; /* default adapter */
+ struct btc_board_info boardInfo;
+ struct btc_bt_info btInfo; /* some bt info referenced by non-bt module */
+ struct btc_stack_info stackInfo;
+ struct btc_bt_link_info btLinkInfo;
+ enum btc_chip_interface chipInterface;
+
+ bool bInitilized;
+ bool bStopCoexDm;
+ bool bManualControl;
+ struct btc_statistics statistics;
+ u8 pwrModeVal[10];
+
+ /* function pointers */
+ /* io related */
+ BFP_BTC_R1 fBtcRead1Byte;
+ BFP_BTC_W1 fBtcWrite1Byte;
+ BFP_BTC_W1_BIT_MASK fBtcWrite1ByteBitMask;
+ BFP_BTC_R2 fBtcRead2Byte;
+ BFP_BTC_W2 fBtcWrite2Byte;
+ BFP_BTC_R4 fBtcRead4Byte;
+ BFP_BTC_W4 fBtcWrite4Byte;
+ BFP_BTC_LOCAL_REG_W1 fBtcWriteLocalReg1Byte;
+ /* read/write bb related */
+ BFP_BTC_SET_BB_REG fBtcSetBbReg;
+ BFP_BTC_GET_BB_REG fBtcGetBbReg;
+
+ /* read/write rf related */
+ BFP_BTC_SET_RF_REG fBtcSetRfReg;
+ BFP_BTC_GET_RF_REG fBtcGetRfReg;
+
+ /* fill h2c related */
+ BFP_BTC_FILL_H2C fBtcFillH2c;
+ /* normal get/set related */
+ BFP_BTC_GET fBtcGet;
+ BFP_BTC_SET fBtcSet;
+
+ BFP_BTC_GET_BT_REG fBtcGetBtReg;
+ BFP_BTC_SET_BT_REG fBtcSetBtReg;
+};
+
+extern struct btc_coexist GLBtCoexist;
+
+void EXhalbtcoutsrc_PowerOnSetting(struct btc_coexist *pBtCoexist);
+void EXhalbtcoutsrc_InitHwConfig(struct btc_coexist *pBtCoexist, u8 bWifiOnly);
+void EXhalbtcoutsrc_InitCoexDm(struct btc_coexist *pBtCoexist);
+void EXhalbtcoutsrc_IpsNotify(struct btc_coexist *pBtCoexist, u8 type);
+void EXhalbtcoutsrc_LpsNotify(struct btc_coexist *pBtCoexist, u8 type);
+void EXhalbtcoutsrc_ScanNotify(struct btc_coexist *pBtCoexist, u8 type);
+void EXhalbtcoutsrc_ConnectNotify(struct btc_coexist *pBtCoexist, u8 action);
+void EXhalbtcoutsrc_MediaStatusNotify(
+ struct btc_coexist *pBtCoexist, enum rt_media_status mediaStatus
+);
+void EXhalbtcoutsrc_SpecialPacketNotify(struct btc_coexist *pBtCoexist, u8 pktType);
+void EXhalbtcoutsrc_BtInfoNotify(
+ struct btc_coexist *pBtCoexist, u8 *tmpBuf, u8 length
+);
+void EXhalbtcoutsrc_HaltNotify(struct btc_coexist *pBtCoexist);
+void EXhalbtcoutsrc_PnpNotify(struct btc_coexist *pBtCoexist, u8 pnpState);
+void EXhalbtcoutsrc_Periodical(struct btc_coexist *pBtCoexist);
+void EXhalbtcoutsrc_SetChipType(u8 chipType);
+void EXhalbtcoutsrc_SetAntNum(u8 type, u8 antNum);
+void EXhalbtcoutsrc_SetSingleAntPath(u8 singleAntPath);
+
+#endif
diff --git a/drivers/staging/rtl8723bs/hal/HalHWImg8723B_BB.c b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_BB.c
new file mode 100644
index 000000000..dd0f74b0c
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_BB.c
@@ -0,0 +1,570 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+*
+* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+*
+******************************************************************************/
+
+#include <linux/kernel.h>
+#include "odm_precomp.h"
+
+static bool CheckPositive(
+ struct dm_odm_t *pDM_Odm, const u32 Condition1, const u32 Condition2
+)
+{
+ u8 _BoardType =
+ ((pDM_Odm->BoardType & BIT4) >> 4) << 0 | /* _GLNA */
+ ((pDM_Odm->BoardType & BIT3) >> 3) << 1 | /* _GPA */
+ ((pDM_Odm->BoardType & BIT7) >> 7) << 2 | /* _ALNA */
+ ((pDM_Odm->BoardType & BIT6) >> 6) << 3 | /* _APA */
+ ((pDM_Odm->BoardType & BIT2) >> 2) << 4; /* _BT */
+
+ u32 cond1 = Condition1, cond2 = Condition2;
+ u32 driver1 =
+ pDM_Odm->CutVersion << 24 |
+ pDM_Odm->SupportPlatform << 16 |
+ pDM_Odm->PackageType << 12 |
+ pDM_Odm->SupportInterface << 8 |
+ _BoardType;
+
+ u32 driver2 =
+ pDM_Odm->TypeGLNA << 0 |
+ pDM_Odm->TypeGPA << 8 |
+ pDM_Odm->TypeALNA << 16 |
+ pDM_Odm->TypeAPA << 24;
+
+
+ /* Value Defined Check =============== */
+ /* QFN Type [15:12] and Cut Version [27:24] need to do value check */
+
+ if (((cond1 & 0x0000F000) != 0) && ((cond1 & 0x0000F000) != (driver1 & 0x0000F000)))
+ return false;
+ if (((cond1 & 0x0F000000) != 0) && ((cond1 & 0x0F000000) != (driver1 & 0x0F000000)))
+ return false;
+
+ /* Bit Defined Check ================ */
+ /* We don't care [31:28] and [23:20] */
+ /* */
+ cond1 &= 0x000F0FFF;
+ driver1 &= 0x000F0FFF;
+
+ if ((cond1 & driver1) == cond1) {
+ u32 bitMask = 0;
+
+ if ((cond1 & 0x0F) == 0) /* BoardType is DONTCARE */
+ return true;
+
+ if ((cond1 & BIT0) != 0) /* GLNA */
+ bitMask |= 0x000000FF;
+ if ((cond1 & BIT1) != 0) /* GPA */
+ bitMask |= 0x0000FF00;
+ if ((cond1 & BIT2) != 0) /* ALNA */
+ bitMask |= 0x00FF0000;
+ if ((cond1 & BIT3) != 0) /* APA */
+ bitMask |= 0xFF000000;
+
+ /* BoardType of each RF path is matched */
+ if ((cond2 & bitMask) == (driver2 & bitMask))
+ return true;
+ }
+ return false;
+}
+
+static bool CheckNegative(
+ struct dm_odm_t *pDM_Odm, const u32 Condition1, const u32 Condition2
+)
+{
+ return true;
+}
+
+/******************************************************************************
+* AGC_TAB.TXT
+******************************************************************************/
+
+static u32 Array_MP_8723B_AGC_TAB[] = {
+ 0xC78, 0xFD000001,
+ 0xC78, 0xFC010001,
+ 0xC78, 0xFB020001,
+ 0xC78, 0xFA030001,
+ 0xC78, 0xF9040001,
+ 0xC78, 0xF8050001,
+ 0xC78, 0xF7060001,
+ 0xC78, 0xF6070001,
+ 0xC78, 0xF5080001,
+ 0xC78, 0xF4090001,
+ 0xC78, 0xF30A0001,
+ 0xC78, 0xF20B0001,
+ 0xC78, 0xF10C0001,
+ 0xC78, 0xF00D0001,
+ 0xC78, 0xEF0E0001,
+ 0xC78, 0xEE0F0001,
+ 0xC78, 0xED100001,
+ 0xC78, 0xEC110001,
+ 0xC78, 0xEB120001,
+ 0xC78, 0xEA130001,
+ 0xC78, 0xE9140001,
+ 0xC78, 0xE8150001,
+ 0xC78, 0xE7160001,
+ 0xC78, 0xE6170001,
+ 0xC78, 0xE5180001,
+ 0xC78, 0xE4190001,
+ 0xC78, 0xE31A0001,
+ 0xC78, 0xA51B0001,
+ 0xC78, 0xA41C0001,
+ 0xC78, 0xA31D0001,
+ 0xC78, 0x671E0001,
+ 0xC78, 0x661F0001,
+ 0xC78, 0x65200001,
+ 0xC78, 0x64210001,
+ 0xC78, 0x63220001,
+ 0xC78, 0x4A230001,
+ 0xC78, 0x49240001,
+ 0xC78, 0x48250001,
+ 0xC78, 0x47260001,
+ 0xC78, 0x46270001,
+ 0xC78, 0x45280001,
+ 0xC78, 0x44290001,
+ 0xC78, 0x432A0001,
+ 0xC78, 0x422B0001,
+ 0xC78, 0x292C0001,
+ 0xC78, 0x282D0001,
+ 0xC78, 0x272E0001,
+ 0xC78, 0x262F0001,
+ 0xC78, 0x0A300001,
+ 0xC78, 0x09310001,
+ 0xC78, 0x08320001,
+ 0xC78, 0x07330001,
+ 0xC78, 0x06340001,
+ 0xC78, 0x05350001,
+ 0xC78, 0x04360001,
+ 0xC78, 0x03370001,
+ 0xC78, 0x02380001,
+ 0xC78, 0x01390001,
+ 0xC78, 0x013A0001,
+ 0xC78, 0x013B0001,
+ 0xC78, 0x013C0001,
+ 0xC78, 0x013D0001,
+ 0xC78, 0x013E0001,
+ 0xC78, 0x013F0001,
+ 0xC78, 0xFC400001,
+ 0xC78, 0xFB410001,
+ 0xC78, 0xFA420001,
+ 0xC78, 0xF9430001,
+ 0xC78, 0xF8440001,
+ 0xC78, 0xF7450001,
+ 0xC78, 0xF6460001,
+ 0xC78, 0xF5470001,
+ 0xC78, 0xF4480001,
+ 0xC78, 0xF3490001,
+ 0xC78, 0xF24A0001,
+ 0xC78, 0xF14B0001,
+ 0xC78, 0xF04C0001,
+ 0xC78, 0xEF4D0001,
+ 0xC78, 0xEE4E0001,
+ 0xC78, 0xED4F0001,
+ 0xC78, 0xEC500001,
+ 0xC78, 0xEB510001,
+ 0xC78, 0xEA520001,
+ 0xC78, 0xE9530001,
+ 0xC78, 0xE8540001,
+ 0xC78, 0xE7550001,
+ 0xC78, 0xE6560001,
+ 0xC78, 0xE5570001,
+ 0xC78, 0xE4580001,
+ 0xC78, 0xE3590001,
+ 0xC78, 0xA65A0001,
+ 0xC78, 0xA55B0001,
+ 0xC78, 0xA45C0001,
+ 0xC78, 0xA35D0001,
+ 0xC78, 0x675E0001,
+ 0xC78, 0x665F0001,
+ 0xC78, 0x65600001,
+ 0xC78, 0x64610001,
+ 0xC78, 0x63620001,
+ 0xC78, 0x62630001,
+ 0xC78, 0x61640001,
+ 0xC78, 0x48650001,
+ 0xC78, 0x47660001,
+ 0xC78, 0x46670001,
+ 0xC78, 0x45680001,
+ 0xC78, 0x44690001,
+ 0xC78, 0x436A0001,
+ 0xC78, 0x426B0001,
+ 0xC78, 0x286C0001,
+ 0xC78, 0x276D0001,
+ 0xC78, 0x266E0001,
+ 0xC78, 0x256F0001,
+ 0xC78, 0x24700001,
+ 0xC78, 0x09710001,
+ 0xC78, 0x08720001,
+ 0xC78, 0x07730001,
+ 0xC78, 0x06740001,
+ 0xC78, 0x05750001,
+ 0xC78, 0x04760001,
+ 0xC78, 0x03770001,
+ 0xC78, 0x02780001,
+ 0xC78, 0x01790001,
+ 0xC78, 0x017A0001,
+ 0xC78, 0x017B0001,
+ 0xC78, 0x017C0001,
+ 0xC78, 0x017D0001,
+ 0xC78, 0x017E0001,
+ 0xC78, 0x017F0001,
+ 0xC50, 0x69553422,
+ 0xC50, 0x69553420,
+ 0x824, 0x00390204,
+
+};
+
+void ODM_ReadAndConfig_MP_8723B_AGC_TAB(struct dm_odm_t *pDM_Odm)
+{
+ u32 i = 0;
+ u32 ArrayLen = ARRAY_SIZE(Array_MP_8723B_AGC_TAB);
+ u32 *Array = Array_MP_8723B_AGC_TAB;
+
+ for (i = 0; i < ArrayLen; i += 2) {
+ u32 v1 = Array[i];
+ u32 v2 = Array[i+1];
+
+ /* This (offset, data) pair doesn't care the condition. */
+ if (v1 < 0x40000000) {
+ odm_ConfigBB_AGC_8723B(pDM_Odm, v1, bMaskDWord, v2);
+ continue;
+ } else {
+ /* This line is the beginning of branch. */
+ bool bMatched = true;
+ u8 cCond = (u8)((v1 & (BIT29|BIT28)) >> 28);
+
+ if (cCond == COND_ELSE) { /* ELSE, ENDIF */
+ bMatched = true;
+ READ_NEXT_PAIR(v1, v2, i);
+ } else if (!CheckPositive(pDM_Odm, v1, v2)) {
+ bMatched = false;
+ READ_NEXT_PAIR(v1, v2, i);
+ READ_NEXT_PAIR(v1, v2, i);
+ } else {
+ READ_NEXT_PAIR(v1, v2, i);
+ if (!CheckNegative(pDM_Odm, v1, v2))
+ bMatched = false;
+ else
+ bMatched = true;
+ READ_NEXT_PAIR(v1, v2, i);
+ }
+
+ if (!bMatched) {
+ /* Condition isn't matched.
+ * Discard the following (offset, data) pairs.
+ */
+ while (v1 < 0x40000000 && i < ArrayLen-2)
+ READ_NEXT_PAIR(v1, v2, i);
+
+ i -= 2; /* prevent from for-loop += 2 */
+ } else {
+ /* Configure matched pairs and skip to end of if-else. */
+ while (v1 < 0x40000000 && i < ArrayLen-2) {
+ odm_ConfigBB_AGC_8723B(pDM_Odm, v1, bMaskDWord, v2);
+ READ_NEXT_PAIR(v1, v2, i);
+ }
+
+ /* Keeps reading until ENDIF. */
+ cCond = (u8)((v1 & (BIT29|BIT28)) >> 28);
+ while (cCond != COND_ENDIF && i < ArrayLen-2) {
+ READ_NEXT_PAIR(v1, v2, i);
+ cCond = (u8)((v1 & (BIT29|BIT28)) >> 28);
+ }
+ }
+ }
+ }
+}
+
+/******************************************************************************
+* PHY_REG.TXT
+******************************************************************************/
+
+static u32 Array_MP_8723B_PHY_REG[] = {
+ 0x800, 0x80040000,
+ 0x804, 0x00000003,
+ 0x808, 0x0000FC00,
+ 0x80C, 0x0000000A,
+ 0x810, 0x10001331,
+ 0x814, 0x020C3D10,
+ 0x818, 0x02200385,
+ 0x81C, 0x00000000,
+ 0x820, 0x01000100,
+ 0x824, 0x00190204,
+ 0x828, 0x00000000,
+ 0x82C, 0x00000000,
+ 0x830, 0x00000000,
+ 0x834, 0x00000000,
+ 0x838, 0x00000000,
+ 0x83C, 0x00000000,
+ 0x840, 0x00010000,
+ 0x844, 0x00000000,
+ 0x848, 0x00000000,
+ 0x84C, 0x00000000,
+ 0x850, 0x00000000,
+ 0x854, 0x00000000,
+ 0x858, 0x569A11A9,
+ 0x85C, 0x01000014,
+ 0x860, 0x66F60110,
+ 0x864, 0x061F0649,
+ 0x868, 0x00000000,
+ 0x86C, 0x27272700,
+ 0x870, 0x07000760,
+ 0x874, 0x25004000,
+ 0x878, 0x00000808,
+ 0x87C, 0x00000000,
+ 0x880, 0xB0000C1C,
+ 0x884, 0x00000001,
+ 0x888, 0x00000000,
+ 0x88C, 0xCCC000C0,
+ 0x890, 0x00000800,
+ 0x894, 0xFFFFFFFE,
+ 0x898, 0x40302010,
+ 0x89C, 0x00706050,
+ 0x900, 0x00000000,
+ 0x904, 0x00000023,
+ 0x908, 0x00000000,
+ 0x90C, 0x81121111,
+ 0x910, 0x00000002,
+ 0x914, 0x00000201,
+ 0xA00, 0x00D047C8,
+ 0xA04, 0x80FF800C,
+ 0xA08, 0x8C838300,
+ 0xA0C, 0x2E7F120F,
+ 0xA10, 0x9500BB78,
+ 0xA14, 0x1114D028,
+ 0xA18, 0x00881117,
+ 0xA1C, 0x89140F00,
+ 0xA20, 0x1A1B0000,
+ 0xA24, 0x090E1317,
+ 0xA28, 0x00000204,
+ 0xA2C, 0x00D30000,
+ 0xA70, 0x101FBF00,
+ 0xA74, 0x00000007,
+ 0xA78, 0x00000900,
+ 0xA7C, 0x225B0606,
+ 0xA80, 0x21806490,
+ 0xB2C, 0x00000000,
+ 0xC00, 0x48071D40,
+ 0xC04, 0x03A05611,
+ 0xC08, 0x000000E4,
+ 0xC0C, 0x6C6C6C6C,
+ 0xC10, 0x08800000,
+ 0xC14, 0x40000100,
+ 0xC18, 0x08800000,
+ 0xC1C, 0x40000100,
+ 0xC20, 0x00000000,
+ 0xC24, 0x00000000,
+ 0xC28, 0x00000000,
+ 0xC2C, 0x00000000,
+ 0xC30, 0x69E9AC44,
+ 0xC34, 0x469652AF,
+ 0xC38, 0x49795994,
+ 0xC3C, 0x0A97971C,
+ 0xC40, 0x1F7C403F,
+ 0xC44, 0x000100B7,
+ 0xC48, 0xEC020107,
+ 0xC4C, 0x007F037F,
+ 0xC50, 0x69553420,
+ 0xC54, 0x43BC0094,
+ 0xC58, 0x00013149,
+ 0xC5C, 0x00250492,
+ 0xC60, 0x00000000,
+ 0xC64, 0x7112848B,
+ 0xC68, 0x47C00BFF,
+ 0xC6C, 0x00000036,
+ 0xC70, 0x2C7F000D,
+ 0xC74, 0x020610DB,
+ 0xC78, 0x0000001F,
+ 0xC7C, 0x00B91612,
+ 0xC80, 0x390000E4,
+ 0xC84, 0x20F60000,
+ 0xC88, 0x40000100,
+ 0xC8C, 0x20200000,
+ 0xC90, 0x00020E1A,
+ 0xC94, 0x00000000,
+ 0xC98, 0x00020E1A,
+ 0xC9C, 0x00007F7F,
+ 0xCA0, 0x00000000,
+ 0xCA4, 0x000300A0,
+ 0xCA8, 0x00000000,
+ 0xCAC, 0x00000000,
+ 0xCB0, 0x00000000,
+ 0xCB4, 0x00000000,
+ 0xCB8, 0x00000000,
+ 0xCBC, 0x28000000,
+ 0xCC0, 0x00000000,
+ 0xCC4, 0x00000000,
+ 0xCC8, 0x00000000,
+ 0xCCC, 0x00000000,
+ 0xCD0, 0x00000000,
+ 0xCD4, 0x00000000,
+ 0xCD8, 0x64B22427,
+ 0xCDC, 0x00766932,
+ 0xCE0, 0x00222222,
+ 0xCE4, 0x00000000,
+ 0xCE8, 0x37644302,
+ 0xCEC, 0x2F97D40C,
+ 0xD00, 0x00000740,
+ 0xD04, 0x40020401,
+ 0xD08, 0x0000907F,
+ 0xD0C, 0x20010201,
+ 0xD10, 0xA0633333,
+ 0xD14, 0x3333BC53,
+ 0xD18, 0x7A8F5B6F,
+ 0xD2C, 0xCC979975,
+ 0xD30, 0x00000000,
+ 0xD34, 0x80608000,
+ 0xD38, 0x00000000,
+ 0xD3C, 0x00127353,
+ 0xD40, 0x00000000,
+ 0xD44, 0x00000000,
+ 0xD48, 0x00000000,
+ 0xD4C, 0x00000000,
+ 0xD50, 0x6437140A,
+ 0xD54, 0x00000000,
+ 0xD58, 0x00000282,
+ 0xD5C, 0x30032064,
+ 0xD60, 0x4653DE68,
+ 0xD64, 0x04518A3C,
+ 0xD68, 0x00002101,
+ 0xD6C, 0x2A201C16,
+ 0xD70, 0x1812362E,
+ 0xD74, 0x322C2220,
+ 0xD78, 0x000E3C24,
+ 0xE00, 0x2D2D2D2D,
+ 0xE04, 0x2D2D2D2D,
+ 0xE08, 0x0390272D,
+ 0xE10, 0x2D2D2D2D,
+ 0xE14, 0x2D2D2D2D,
+ 0xE18, 0x2D2D2D2D,
+ 0xE1C, 0x2D2D2D2D,
+ 0xE28, 0x00000000,
+ 0xE30, 0x1000DC1F,
+ 0xE34, 0x10008C1F,
+ 0xE38, 0x02140102,
+ 0xE3C, 0x681604C2,
+ 0xE40, 0x01007C00,
+ 0xE44, 0x01004800,
+ 0xE48, 0xFB000000,
+ 0xE4C, 0x000028D1,
+ 0xE50, 0x1000DC1F,
+ 0xE54, 0x10008C1F,
+ 0xE58, 0x02140102,
+ 0xE5C, 0x28160D05,
+ 0xE60, 0x00000008,
+ 0xE68, 0x001B2556,
+ 0xE6C, 0x00C00096,
+ 0xE70, 0x00C00096,
+ 0xE74, 0x01000056,
+ 0xE78, 0x01000014,
+ 0xE7C, 0x01000056,
+ 0xE80, 0x01000014,
+ 0xE84, 0x00C00096,
+ 0xE88, 0x01000056,
+ 0xE8C, 0x00C00096,
+ 0xED0, 0x00C00096,
+ 0xED4, 0x00C00096,
+ 0xED8, 0x00C00096,
+ 0xEDC, 0x000000D6,
+ 0xEE0, 0x000000D6,
+ 0xEEC, 0x01C00016,
+ 0xF14, 0x00000003,
+ 0xF4C, 0x00000000,
+ 0xF00, 0x00000300,
+ 0x820, 0x01000100,
+ 0x800, 0x83040000,
+
+};
+
+void ODM_ReadAndConfig_MP_8723B_PHY_REG(struct dm_odm_t *pDM_Odm)
+{
+ u32 i = 0;
+ u32 ArrayLen = ARRAY_SIZE(Array_MP_8723B_PHY_REG);
+ u32 *Array = Array_MP_8723B_PHY_REG;
+
+ for (i = 0; i < ArrayLen; i += 2) {
+ u32 v1 = Array[i];
+ u32 v2 = Array[i+1];
+
+ /* This (offset, data) pair doesn't care the condition. */
+ if (v1 < 0x40000000) {
+ odm_ConfigBB_PHY_8723B(pDM_Odm, v1, bMaskDWord, v2);
+ continue;
+ } else {
+ /* This line is the beginning of branch. */
+ bool bMatched = true;
+ u8 cCond = (u8)((v1 & (BIT29|BIT28)) >> 28);
+
+ if (cCond == COND_ELSE) { /* ELSE, ENDIF */
+ bMatched = true;
+ READ_NEXT_PAIR(v1, v2, i);
+ } else if (!CheckPositive(pDM_Odm, v1, v2)) {
+ bMatched = false;
+ READ_NEXT_PAIR(v1, v2, i);
+ READ_NEXT_PAIR(v1, v2, i);
+ } else {
+ READ_NEXT_PAIR(v1, v2, i);
+ if (!CheckNegative(pDM_Odm, v1, v2))
+ bMatched = false;
+ else
+ bMatched = true;
+ READ_NEXT_PAIR(v1, v2, i);
+ }
+
+ if (!bMatched) {
+ /* Condition isn't matched.
+ * Discard the following (offset, data) pairs.
+ */
+ while (v1 < 0x40000000 && i < ArrayLen-2)
+ READ_NEXT_PAIR(v1, v2, i);
+
+ i -= 2; /* prevent from for-loop += 2 */
+ } else { /* Configure matched pairs and skip to end of if-else. */
+ while (v1 < 0x40000000 && i < ArrayLen-2) {
+ odm_ConfigBB_PHY_8723B(pDM_Odm, v1, bMaskDWord, v2);
+ READ_NEXT_PAIR(v1, v2, i);
+ }
+
+ /* Keeps reading until ENDIF. */
+ cCond = (u8)((v1 & (BIT29|BIT28)) >> 28);
+ while (cCond != COND_ENDIF && i < ArrayLen-2) {
+ READ_NEXT_PAIR(v1, v2, i);
+ cCond = (u8)((v1 & (BIT29|BIT28)) >> 28);
+ }
+ }
+ }
+ }
+}
+
+/******************************************************************************
+* PHY_REG_PG.TXT
+******************************************************************************/
+
+static u32 Array_MP_8723B_PHY_REG_PG[] = {
+ 0, 0x00000e08, 0x0000ff00, 0x00003800,
+ 0, 0x0000086c, 0xffffff00, 0x32343600,
+ 0, 0x00000e00, 0xffffffff, 0x40424444,
+ 0, 0x00000e04, 0xffffffff, 0x28323638,
+ 0, 0x00000e10, 0xffffffff, 0x38404244,
+ 0, 0x00000e14, 0xffffffff, 0x26303436
+};
+
+void ODM_ReadAndConfig_MP_8723B_PHY_REG_PG(struct dm_odm_t *pDM_Odm)
+{
+ u32 i = 0;
+ u32 *Array = Array_MP_8723B_PHY_REG_PG;
+
+ pDM_Odm->PhyRegPgVersion = 1;
+ pDM_Odm->PhyRegPgValueType = PHY_REG_PG_EXACT_VALUE;
+
+ for (i = 0; i < ARRAY_SIZE(Array_MP_8723B_PHY_REG_PG); i += 4) {
+ u32 v1 = Array[i];
+ u32 v2 = Array[i+1];
+ u32 v3 = Array[i+2];
+ u32 v4 = Array[i+3];
+
+ odm_ConfigBB_PHY_REG_PG_8723B(pDM_Odm, v1, v2, v3, v4);
+ }
+}
diff --git a/drivers/staging/rtl8723bs/hal/HalHWImg8723B_BB.h b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_BB.h
new file mode 100644
index 000000000..186007ce5
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_BB.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+*
+* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+*
+******************************************************************************/
+
+#ifndef __INC_MP_BB_HW_IMG_8723B_H
+#define __INC_MP_BB_HW_IMG_8723B_H
+
+
+/******************************************************************************
+* AGC_TAB.TXT
+******************************************************************************/
+
+void
+ODM_ReadAndConfig_MP_8723B_AGC_TAB(/* TC: Test Chip, MP: MP Chip */
+ struct dm_odm_t *pDM_Odm
+);
+
+/******************************************************************************
+* PHY_REG.TXT
+******************************************************************************/
+
+void
+ODM_ReadAndConfig_MP_8723B_PHY_REG(/* TC: Test Chip, MP: MP Chip */
+ struct dm_odm_t *pDM_Odm
+);
+
+/******************************************************************************
+* PHY_REG_PG.TXT
+******************************************************************************/
+
+void
+ODM_ReadAndConfig_MP_8723B_PHY_REG_PG(/* TC: Test Chip, MP: MP Chip */
+ struct dm_odm_t *pDM_Odm
+);
+u32 ODM_GetVersion_MP_8723B_PHY_REG_PG(void);
+
+#endif
diff --git a/drivers/staging/rtl8723bs/hal/HalHWImg8723B_MAC.c b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_MAC.c
new file mode 100644
index 000000000..47e66f4ad
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_MAC.c
@@ -0,0 +1,245 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+*
+* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+*
+******************************************************************************/
+
+#include <linux/kernel.h>
+#include "odm_precomp.h"
+
+static bool CheckPositive(
+ struct dm_odm_t *pDM_Odm, const u32 Condition1, const u32 Condition2
+)
+{
+ u8 _BoardType =
+ ((pDM_Odm->BoardType & BIT4) >> 4) << 0 | /* _GLNA */
+ ((pDM_Odm->BoardType & BIT3) >> 3) << 1 | /* _GPA */
+ ((pDM_Odm->BoardType & BIT7) >> 7) << 2 | /* _ALNA */
+ ((pDM_Odm->BoardType & BIT6) >> 6) << 3 | /* _APA */
+ ((pDM_Odm->BoardType & BIT2) >> 2) << 4; /* _BT */
+
+ u32 cond1 = Condition1, cond2 = Condition2;
+ u32 driver1 =
+ pDM_Odm->CutVersion << 24 |
+ pDM_Odm->SupportPlatform << 16 |
+ pDM_Odm->PackageType << 12 |
+ pDM_Odm->SupportInterface << 8 |
+ _BoardType;
+
+ u32 driver2 =
+ pDM_Odm->TypeGLNA << 0 |
+ pDM_Odm->TypeGPA << 8 |
+ pDM_Odm->TypeALNA << 16 |
+ pDM_Odm->TypeAPA << 24;
+
+
+ /* Value Defined Check =============== */
+ /* QFN Type [15:12] and Cut Version [27:24] need to do value check */
+
+ if (((cond1 & 0x0000F000) != 0) && ((cond1 & 0x0000F000) != (driver1 & 0x0000F000)))
+ return false;
+ if (((cond1 & 0x0F000000) != 0) && ((cond1 & 0x0F000000) != (driver1 & 0x0F000000)))
+ return false;
+
+ /* Bit Defined Check ================ */
+ /* We don't care [31:28] and [23:20] */
+ /* */
+ cond1 &= 0x000F0FFF;
+ driver1 &= 0x000F0FFF;
+
+ if ((cond1 & driver1) == cond1) {
+ u32 bitMask = 0;
+ if ((cond1 & 0x0F) == 0) /* BoardType is DONTCARE */
+ return true;
+
+ if ((cond1 & BIT0) != 0) /* GLNA */
+ bitMask |= 0x000000FF;
+ if ((cond1 & BIT1) != 0) /* GPA */
+ bitMask |= 0x0000FF00;
+ if ((cond1 & BIT2) != 0) /* ALNA */
+ bitMask |= 0x00FF0000;
+ if ((cond1 & BIT3) != 0) /* APA */
+ bitMask |= 0xFF000000;
+
+ if ((cond2 & bitMask) == (driver2 & bitMask)) /* BoardType of each RF path is matched */
+ return true;
+ }
+ return false;
+}
+
+static bool CheckNegative(
+ struct dm_odm_t *pDM_Odm, const u32 Condition1, const u32 Condition2
+)
+{
+ return true;
+}
+
+/******************************************************************************
+* MAC_REG.TXT
+******************************************************************************/
+
+static u32 Array_MP_8723B_MAC_REG[] = {
+ 0x02F, 0x00000030,
+ 0x035, 0x00000000,
+ 0x039, 0x00000008,
+ 0x04E, 0x000000E0,
+ 0x064, 0x00000000,
+ 0x067, 0x00000020,
+ 0x428, 0x0000000A,
+ 0x429, 0x00000010,
+ 0x430, 0x00000000,
+ 0x431, 0x00000000,
+ 0x432, 0x00000000,
+ 0x433, 0x00000001,
+ 0x434, 0x00000004,
+ 0x435, 0x00000005,
+ 0x436, 0x00000007,
+ 0x437, 0x00000008,
+ 0x43C, 0x00000004,
+ 0x43D, 0x00000005,
+ 0x43E, 0x00000007,
+ 0x43F, 0x00000008,
+ 0x440, 0x0000005D,
+ 0x441, 0x00000001,
+ 0x442, 0x00000000,
+ 0x444, 0x00000010,
+ 0x445, 0x00000000,
+ 0x446, 0x00000000,
+ 0x447, 0x00000000,
+ 0x448, 0x00000000,
+ 0x449, 0x000000F0,
+ 0x44A, 0x0000000F,
+ 0x44B, 0x0000003E,
+ 0x44C, 0x00000010,
+ 0x44D, 0x00000000,
+ 0x44E, 0x00000000,
+ 0x44F, 0x00000000,
+ 0x450, 0x00000000,
+ 0x451, 0x000000F0,
+ 0x452, 0x0000000F,
+ 0x453, 0x00000000,
+ 0x456, 0x0000005E,
+ 0x460, 0x00000066,
+ 0x461, 0x00000066,
+ 0x4C8, 0x000000FF,
+ 0x4C9, 0x00000008,
+ 0x4CC, 0x000000FF,
+ 0x4CD, 0x000000FF,
+ 0x4CE, 0x00000001,
+ 0x500, 0x00000026,
+ 0x501, 0x000000A2,
+ 0x502, 0x0000002F,
+ 0x503, 0x00000000,
+ 0x504, 0x00000028,
+ 0x505, 0x000000A3,
+ 0x506, 0x0000005E,
+ 0x507, 0x00000000,
+ 0x508, 0x0000002B,
+ 0x509, 0x000000A4,
+ 0x50A, 0x0000005E,
+ 0x50B, 0x00000000,
+ 0x50C, 0x0000004F,
+ 0x50D, 0x000000A4,
+ 0x50E, 0x00000000,
+ 0x50F, 0x00000000,
+ 0x512, 0x0000001C,
+ 0x514, 0x0000000A,
+ 0x516, 0x0000000A,
+ 0x525, 0x0000004F,
+ 0x550, 0x00000010,
+ 0x551, 0x00000010,
+ 0x559, 0x00000002,
+ 0x55C, 0x00000050,
+ 0x55D, 0x000000FF,
+ 0x605, 0x00000030,
+ 0x608, 0x0000000E,
+ 0x609, 0x0000002A,
+ 0x620, 0x000000FF,
+ 0x621, 0x000000FF,
+ 0x622, 0x000000FF,
+ 0x623, 0x000000FF,
+ 0x624, 0x000000FF,
+ 0x625, 0x000000FF,
+ 0x626, 0x000000FF,
+ 0x627, 0x000000FF,
+ 0x638, 0x00000050,
+ 0x63C, 0x0000000A,
+ 0x63D, 0x0000000A,
+ 0x63E, 0x0000000E,
+ 0x63F, 0x0000000E,
+ 0x640, 0x00000040,
+ 0x642, 0x00000040,
+ 0x643, 0x00000000,
+ 0x652, 0x000000C8,
+ 0x66E, 0x00000005,
+ 0x700, 0x00000021,
+ 0x701, 0x00000043,
+ 0x702, 0x00000065,
+ 0x703, 0x00000087,
+ 0x708, 0x00000021,
+ 0x709, 0x00000043,
+ 0x70A, 0x00000065,
+ 0x70B, 0x00000087,
+ 0x765, 0x00000018,
+ 0x76E, 0x00000004,
+
+};
+
+void ODM_ReadAndConfig_MP_8723B_MAC_REG(struct dm_odm_t *pDM_Odm)
+{
+ u32 i = 0;
+ u32 ArrayLen = ARRAY_SIZE(Array_MP_8723B_MAC_REG);
+ u32 *Array = Array_MP_8723B_MAC_REG;
+
+ for (i = 0; i < ArrayLen; i += 2) {
+ u32 v1 = Array[i];
+ u32 v2 = Array[i+1];
+
+ /* This (offset, data) pair doesn't care the condition. */
+ if (v1 < 0x40000000) {
+ odm_ConfigMAC_8723B(pDM_Odm, v1, (u8)v2);
+ continue;
+ } else {
+ /* This line is the beginning of branch. */
+ bool bMatched = true;
+ u8 cCond = (u8)((v1 & (BIT29|BIT28)) >> 28);
+
+ if (cCond == COND_ELSE) { /* ELSE, ENDIF */
+ bMatched = true;
+ READ_NEXT_PAIR(v1, v2, i);
+ } else if (!CheckPositive(pDM_Odm, v1, v2)) {
+ bMatched = false;
+ READ_NEXT_PAIR(v1, v2, i);
+ READ_NEXT_PAIR(v1, v2, i);
+ } else {
+ READ_NEXT_PAIR(v1, v2, i);
+ if (!CheckNegative(pDM_Odm, v1, v2))
+ bMatched = false;
+ else
+ bMatched = true;
+ READ_NEXT_PAIR(v1, v2, i);
+ }
+
+ if (!bMatched) {
+ /* Condition isn't matched. Discard the following (offset, data) pairs. */
+ while (v1 < 0x40000000 && i < ArrayLen-2)
+ READ_NEXT_PAIR(v1, v2, i);
+
+ i -= 2; /* prevent from for-loop += 2 */
+ } else { /* Configure matched pairs and skip to end of if-else. */
+ while (v1 < 0x40000000 && i < ArrayLen-2) {
+ odm_ConfigMAC_8723B(pDM_Odm, v1, (u8)v2);
+ READ_NEXT_PAIR(v1, v2, i);
+ }
+
+ /* Keeps reading until ENDIF. */
+ cCond = (u8)((v1 & (BIT29|BIT28)) >> 28);
+ while (cCond != COND_ENDIF && i < ArrayLen-2) {
+ READ_NEXT_PAIR(v1, v2, i);
+ cCond = (u8)((v1 & (BIT29|BIT28)) >> 28);
+ }
+ }
+ }
+ }
+}
diff --git a/drivers/staging/rtl8723bs/hal/HalHWImg8723B_MAC.h b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_MAC.h
new file mode 100644
index 000000000..50429c159
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_MAC.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+*
+* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+*
+******************************************************************************/
+
+#ifndef __INC_MP_MAC_HW_IMG_8723B_H
+#define __INC_MP_MAC_HW_IMG_8723B_H
+
+
+/******************************************************************************
+* MAC_REG.TXT
+******************************************************************************/
+
+void
+ODM_ReadAndConfig_MP_8723B_MAC_REG(/* TC: Test Chip, MP: MP Chip */
+ struct dm_odm_t *pDM_Odm
+);
+#endif
diff --git a/drivers/staging/rtl8723bs/hal/HalHWImg8723B_RF.c b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_RF.c
new file mode 100644
index 000000000..efc68c17b
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_RF.c
@@ -0,0 +1,564 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+*
+* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+*
+******************************************************************************/
+
+#include <linux/kernel.h>
+#include "odm_precomp.h"
+
+static bool CheckPositive(
+ struct dm_odm_t *pDM_Odm, const u32 Condition1, const u32 Condition2
+)
+{
+ u8 _BoardType =
+ ((pDM_Odm->BoardType & BIT4) >> 4) << 0 | /* _GLNA */
+ ((pDM_Odm->BoardType & BIT3) >> 3) << 1 | /* _GPA */
+ ((pDM_Odm->BoardType & BIT7) >> 7) << 2 | /* _ALNA */
+ ((pDM_Odm->BoardType & BIT6) >> 6) << 3 | /* _APA */
+ ((pDM_Odm->BoardType & BIT2) >> 2) << 4; /* _BT */
+
+ u32 cond1 = Condition1, cond2 = Condition2;
+ u32 driver1 =
+ pDM_Odm->CutVersion << 24 |
+ pDM_Odm->SupportPlatform << 16 |
+ pDM_Odm->PackageType << 12 |
+ pDM_Odm->SupportInterface << 8 |
+ _BoardType;
+
+ u32 driver2 =
+ pDM_Odm->TypeGLNA << 0 |
+ pDM_Odm->TypeGPA << 8 |
+ pDM_Odm->TypeALNA << 16 |
+ pDM_Odm->TypeAPA << 24;
+
+ /* Value Defined Check =============== */
+ /* QFN Type [15:12] and Cut Version [27:24] need to do value check */
+
+ if (
+ ((cond1 & 0x0000F000) != 0) &&
+ ((cond1 & 0x0000F000) != (driver1 & 0x0000F000))
+ )
+ return false;
+
+ if (
+ ((cond1 & 0x0F000000) != 0) &&
+ ((cond1 & 0x0F000000) != (driver1 & 0x0F000000))
+ )
+ return false;
+
+ /* Bit Defined Check ================ */
+ /* We don't care [31:28] and [23:20] */
+ cond1 &= 0x000F0FFF;
+ driver1 &= 0x000F0FFF;
+
+ if ((cond1 & driver1) == cond1) {
+ u32 bitMask = 0;
+
+ if ((cond1 & 0x0F) == 0) /* BoardType is DONTCARE */
+ return true;
+
+ if ((cond1 & BIT0) != 0) /* GLNA */
+ bitMask |= 0x000000FF;
+ if ((cond1 & BIT1) != 0) /* GPA */
+ bitMask |= 0x0000FF00;
+ if ((cond1 & BIT2) != 0) /* ALNA */
+ bitMask |= 0x00FF0000;
+ if ((cond1 & BIT3) != 0) /* APA */
+ bitMask |= 0xFF000000;
+
+ /* BoardType of each RF path is matched */
+ if ((cond2 & bitMask) == (driver2 & bitMask))
+ return true;
+
+ return false;
+ }
+
+ return false;
+}
+
+static bool CheckNegative(
+ struct dm_odm_t *pDM_Odm, const u32 Condition1, const u32 Condition2
+)
+{
+ return true;
+}
+
+/******************************************************************************
+* RadioA.TXT
+******************************************************************************/
+
+static u32 Array_MP_8723B_RadioA[] = {
+ 0x000, 0x00010000,
+ 0x0B0, 0x000DFFE0,
+ 0x0FE, 0x00000000,
+ 0x0FE, 0x00000000,
+ 0x0FE, 0x00000000,
+ 0x0B1, 0x00000018,
+ 0x0FE, 0x00000000,
+ 0x0FE, 0x00000000,
+ 0x0FE, 0x00000000,
+ 0x0B2, 0x00084C00,
+ 0x0B5, 0x0000D2CC,
+ 0x0B6, 0x000925AA,
+ 0x0B7, 0x00000010,
+ 0x0B8, 0x0000907F,
+ 0x05C, 0x00000002,
+ 0x07C, 0x00000002,
+ 0x07E, 0x00000005,
+ 0x08B, 0x0006FC00,
+ 0x0B0, 0x000FF9F0,
+ 0x01C, 0x000739D2,
+ 0x01E, 0x00000000,
+ 0x0DF, 0x00000780,
+ 0x050, 0x00067435,
+ 0x80002000, 0x00000000, 0x40000000, 0x00000000,
+ 0x051, 0x0006B10E,
+ 0x90003000, 0x00000000, 0x40000000, 0x00000000,
+ 0x051, 0x0006B10E,
+ 0x90004000, 0x00000000, 0x40000000, 0x00000000,
+ 0x051, 0x0006B10E,
+ 0xA0000000, 0x00000000,
+ 0x051, 0x0006B04E,
+ 0xB0000000, 0x00000000,
+ 0x052, 0x000007D2,
+ 0x053, 0x00000000,
+ 0x054, 0x00050400,
+ 0x055, 0x0004026E,
+ 0x0DD, 0x0000004C,
+ 0x070, 0x00067435,
+ 0x80002000, 0x00000000, 0x40000000, 0x00000000,
+ 0x071, 0x0006B10E,
+ 0x90003000, 0x00000000, 0x40000000, 0x00000000,
+ 0x071, 0x0006B10E,
+ 0x90004000, 0x00000000, 0x40000000, 0x00000000,
+ 0x071, 0x0006B10E,
+ 0xA0000000, 0x00000000,
+ 0x071, 0x0006B04E,
+ 0xB0000000, 0x00000000,
+ 0x072, 0x000007D2,
+ 0x073, 0x00000000,
+ 0x074, 0x00050400,
+ 0x075, 0x0004026E,
+ 0x0EF, 0x00000100,
+ 0x034, 0x0000ADD7,
+ 0x035, 0x00005C00,
+ 0x034, 0x00009DD4,
+ 0x035, 0x00005000,
+ 0x034, 0x00008DD1,
+ 0x035, 0x00004400,
+ 0x034, 0x00007DCE,
+ 0x035, 0x00003800,
+ 0x034, 0x00006CD1,
+ 0x035, 0x00004400,
+ 0x034, 0x00005CCE,
+ 0x035, 0x00003800,
+ 0x034, 0x000048CE,
+ 0x035, 0x00004400,
+ 0x034, 0x000034CE,
+ 0x035, 0x00003800,
+ 0x034, 0x00002451,
+ 0x035, 0x00004400,
+ 0x034, 0x0000144E,
+ 0x035, 0x00003800,
+ 0x034, 0x00000051,
+ 0x035, 0x00004400,
+ 0x0EF, 0x00000000,
+ 0x0EF, 0x00000100,
+ 0x0ED, 0x00000010,
+ 0x044, 0x0000ADD7,
+ 0x044, 0x00009DD4,
+ 0x044, 0x00008DD1,
+ 0x044, 0x00007DCE,
+ 0x044, 0x00006CC1,
+ 0x044, 0x00005CCE,
+ 0x044, 0x000044D1,
+ 0x044, 0x000034CE,
+ 0x044, 0x00002451,
+ 0x044, 0x0000144E,
+ 0x044, 0x00000051,
+ 0x0EF, 0x00000000,
+ 0x0ED, 0x00000000,
+ 0x07F, 0x00020080,
+ 0x0EF, 0x00002000,
+ 0x03B, 0x000380EF,
+ 0x03B, 0x000302FE,
+ 0x03B, 0x00028CE6,
+ 0x03B, 0x000200BC,
+ 0x03B, 0x000188A5,
+ 0x03B, 0x00010FBC,
+ 0x03B, 0x00008F71,
+ 0x03B, 0x00000900,
+ 0x0EF, 0x00000000,
+ 0x0ED, 0x00000001,
+ 0x040, 0x000380EF,
+ 0x040, 0x000302FE,
+ 0x040, 0x00028CE6,
+ 0x040, 0x000200BC,
+ 0x040, 0x000188A5,
+ 0x040, 0x00010FBC,
+ 0x040, 0x00008F71,
+ 0x040, 0x00000900,
+ 0x0ED, 0x00000000,
+ 0x082, 0x00080000,
+ 0x083, 0x00008000,
+ 0x084, 0x00048D80,
+ 0x085, 0x00068000,
+ 0x0A2, 0x00080000,
+ 0x0A3, 0x00008000,
+ 0x0A4, 0x00048D80,
+ 0x0A5, 0x00068000,
+ 0x0ED, 0x00000002,
+ 0x0EF, 0x00000002,
+ 0x056, 0x00000032,
+ 0x076, 0x00000032,
+ 0x001, 0x00000780,
+
+};
+
+void ODM_ReadAndConfig_MP_8723B_RadioA(struct dm_odm_t *pDM_Odm)
+{
+ u32 i = 0;
+ u32 ArrayLen = ARRAY_SIZE(Array_MP_8723B_RadioA);
+ u32 *Array = Array_MP_8723B_RadioA;
+
+ for (i = 0; i < ArrayLen; i += 2) {
+ u32 v1 = Array[i];
+ u32 v2 = Array[i+1];
+
+ /* This (offset, data) pair doesn't care the condition. */
+ if (v1 < 0x40000000) {
+ odm_ConfigRF_RadioA_8723B(pDM_Odm, v1, v2);
+ continue;
+ } else {
+ /* This line is the beginning of branch. */
+ bool bMatched = true;
+ u8 cCond = (u8)((v1 & (BIT29|BIT28)) >> 28);
+
+ if (cCond == COND_ELSE) { /* ELSE, ENDIF */
+ bMatched = true;
+ READ_NEXT_PAIR(v1, v2, i);
+ } else if (!CheckPositive(pDM_Odm, v1, v2)) {
+ bMatched = false;
+ READ_NEXT_PAIR(v1, v2, i);
+ READ_NEXT_PAIR(v1, v2, i);
+ } else {
+ READ_NEXT_PAIR(v1, v2, i);
+ if (!CheckNegative(pDM_Odm, v1, v2))
+ bMatched = false;
+ else
+ bMatched = true;
+ READ_NEXT_PAIR(v1, v2, i);
+ }
+
+ if (!bMatched) {
+ /* Condition isn't matched.
+ * Discard the following (offset, data) pairs.
+ */
+ while (v1 < 0x40000000 && i < ArrayLen-2)
+ READ_NEXT_PAIR(v1, v2, i);
+
+ i -= 2; /* prevent from for-loop += 2 */
+ } else {
+ /* Configure matched pairs and skip to end of if-else. */
+ while (v1 < 0x40000000 && i < ArrayLen-2) {
+ odm_ConfigRF_RadioA_8723B(pDM_Odm, v1, v2);
+ READ_NEXT_PAIR(v1, v2, i);
+ }
+
+ /* Keeps reading until ENDIF. */
+ cCond = (u8)((v1 & (BIT29|BIT28)) >> 28);
+ while (cCond != COND_ENDIF && i < ArrayLen-2) {
+ READ_NEXT_PAIR(v1, v2, i);
+ cCond = (u8)((v1 & (BIT29|BIT28)) >> 28);
+ }
+ }
+ }
+ }
+}
+
+/******************************************************************************
+* TxPowerTrack_SDIO.TXT
+******************************************************************************/
+
+static u8 gDeltaSwingTableIdx_MP_2GB_N_TxPowerTrack_SDIO_8723B[] = {
+ 0, 0, 1, 2, 2, 2, 3, 3, 3, 4, 5, 5, 6, 6, 6, 6,
+ 7, 7, 7, 8, 8, 9, 9, 10, 10, 11, 12, 13, 14, 15
+};
+static u8 gDeltaSwingTableIdx_MP_2GB_P_TxPowerTrack_SDIO_8723B[] = {
+ 0, 0, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6, 7, 7, 8, 8,
+ 9, 9, 10, 10, 10, 11, 11, 12, 12, 13, 13, 14, 15, 15
+};
+static u8 gDeltaSwingTableIdx_MP_2GA_N_TxPowerTrack_SDIO_8723B[] = {
+ 0, 0, 1, 2, 2, 2, 3, 3, 3, 4, 5, 5, 6, 6, 6, 6,
+ 7, 7, 7, 8, 8, 9, 9, 10, 10, 11, 12, 13, 14, 15
+};
+static u8 gDeltaSwingTableIdx_MP_2GA_P_TxPowerTrack_SDIO_8723B[] = {
+ 0, 0, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6, 7, 7, 8, 8,
+ 9, 9, 10, 10, 10, 11, 11, 12, 12, 13, 13, 14, 15, 15
+};
+static u8 gDeltaSwingTableIdx_MP_2GCCKB_N_TxPowerTrack_SDIO_8723B[] = {
+ 0, 0, 1, 2, 2, 3, 3, 4, 4, 5, 6, 6, 7, 7, 7, 8,
+ 8, 8, 9, 9, 9, 10, 10, 11, 11, 12, 12, 13, 14, 15
+};
+static u8 gDeltaSwingTableIdx_MP_2GCCKB_P_TxPowerTrack_SDIO_8723B[] = {
+ 0, 0, 1, 2, 2, 2, 3, 3, 3, 4, 5, 5, 6, 6, 7, 7,
+ 8, 8, 9, 9, 9, 10, 10, 11, 11, 12, 12, 13, 14, 15
+};
+static u8 gDeltaSwingTableIdx_MP_2GCCKA_N_TxPowerTrack_SDIO_8723B[] = {
+ 0, 0, 1, 2, 2, 3, 3, 4, 4, 5, 6, 6, 7, 7, 7, 8,
+ 8, 8, 9, 9, 9, 10, 10, 11, 11, 12, 12, 13, 14, 15
+};
+static u8 gDeltaSwingTableIdx_MP_2GCCKA_P_TxPowerTrack_SDIO_8723B[] = {
+ 0, 0, 1, 2, 2, 2, 3, 3, 3, 4, 5, 5, 6, 6, 7, 7,
+ 8, 8, 9, 9, 9, 10, 10, 11, 11, 12, 12, 13, 14, 15
+};
+
+void ODM_ReadAndConfig_MP_8723B_TxPowerTrack_SDIO(struct dm_odm_t *pDM_Odm)
+{
+ struct odm_rf_cal_t *pRFCalibrateInfo = &pDM_Odm->RFCalibrateInfo;
+
+
+ memcpy(
+ pRFCalibrateInfo->DeltaSwingTableIdx_2GA_P,
+ gDeltaSwingTableIdx_MP_2GA_P_TxPowerTrack_SDIO_8723B,
+ DELTA_SWINGIDX_SIZE
+ );
+ memcpy(
+ pRFCalibrateInfo->DeltaSwingTableIdx_2GA_N,
+ gDeltaSwingTableIdx_MP_2GA_N_TxPowerTrack_SDIO_8723B,
+ DELTA_SWINGIDX_SIZE
+ );
+ memcpy(
+ pRFCalibrateInfo->DeltaSwingTableIdx_2GB_P,
+ gDeltaSwingTableIdx_MP_2GB_P_TxPowerTrack_SDIO_8723B,
+ DELTA_SWINGIDX_SIZE
+ );
+ memcpy(
+ pRFCalibrateInfo->DeltaSwingTableIdx_2GB_N,
+ gDeltaSwingTableIdx_MP_2GB_N_TxPowerTrack_SDIO_8723B,
+ DELTA_SWINGIDX_SIZE
+ );
+
+ memcpy(
+ pRFCalibrateInfo->DeltaSwingTableIdx_2GCCKA_P,
+ gDeltaSwingTableIdx_MP_2GCCKA_P_TxPowerTrack_SDIO_8723B,
+ DELTA_SWINGIDX_SIZE
+ );
+ memcpy(
+ pRFCalibrateInfo->DeltaSwingTableIdx_2GCCKA_N,
+ gDeltaSwingTableIdx_MP_2GCCKA_N_TxPowerTrack_SDIO_8723B,
+ DELTA_SWINGIDX_SIZE
+ );
+ memcpy(
+ pRFCalibrateInfo->DeltaSwingTableIdx_2GCCKB_P,
+ gDeltaSwingTableIdx_MP_2GCCKB_P_TxPowerTrack_SDIO_8723B,
+ DELTA_SWINGIDX_SIZE
+ );
+ memcpy(
+ pRFCalibrateInfo->DeltaSwingTableIdx_2GCCKB_N,
+ gDeltaSwingTableIdx_MP_2GCCKB_N_TxPowerTrack_SDIO_8723B,
+ DELTA_SWINGIDX_SIZE
+ );
+}
+
+/******************************************************************************
+* TXPWR_LMT.TXT
+******************************************************************************/
+
+static u8 *Array_MP_8723B_TXPWR_LMT[] = {
+ "FCC", "20M", "CCK", "1T", "01", "32",
+ "ETSI", "20M", "CCK", "1T", "01", "32",
+ "MKK", "20M", "CCK", "1T", "01", "32",
+ "FCC", "20M", "CCK", "1T", "02", "32",
+ "ETSI", "20M", "CCK", "1T", "02", "32",
+ "MKK", "20M", "CCK", "1T", "02", "32",
+ "FCC", "20M", "CCK", "1T", "03", "32",
+ "ETSI", "20M", "CCK", "1T", "03", "32",
+ "MKK", "20M", "CCK", "1T", "03", "32",
+ "FCC", "20M", "CCK", "1T", "04", "32",
+ "ETSI", "20M", "CCK", "1T", "04", "32",
+ "MKK", "20M", "CCK", "1T", "04", "32",
+ "FCC", "20M", "CCK", "1T", "05", "32",
+ "ETSI", "20M", "CCK", "1T", "05", "32",
+ "MKK", "20M", "CCK", "1T", "05", "32",
+ "FCC", "20M", "CCK", "1T", "06", "32",
+ "ETSI", "20M", "CCK", "1T", "06", "32",
+ "MKK", "20M", "CCK", "1T", "06", "32",
+ "FCC", "20M", "CCK", "1T", "07", "32",
+ "ETSI", "20M", "CCK", "1T", "07", "32",
+ "MKK", "20M", "CCK", "1T", "07", "32",
+ "FCC", "20M", "CCK", "1T", "08", "32",
+ "ETSI", "20M", "CCK", "1T", "08", "32",
+ "MKK", "20M", "CCK", "1T", "08", "32",
+ "FCC", "20M", "CCK", "1T", "09", "32",
+ "ETSI", "20M", "CCK", "1T", "09", "32",
+ "MKK", "20M", "CCK", "1T", "09", "32",
+ "FCC", "20M", "CCK", "1T", "10", "32",
+ "ETSI", "20M", "CCK", "1T", "10", "32",
+ "MKK", "20M", "CCK", "1T", "10", "32",
+ "FCC", "20M", "CCK", "1T", "11", "32",
+ "ETSI", "20M", "CCK", "1T", "11", "32",
+ "MKK", "20M", "CCK", "1T", "11", "32",
+ "FCC", "20M", "CCK", "1T", "12", "63",
+ "ETSI", "20M", "CCK", "1T", "12", "32",
+ "MKK", "20M", "CCK", "1T", "12", "32",
+ "FCC", "20M", "CCK", "1T", "13", "63",
+ "ETSI", "20M", "CCK", "1T", "13", "32",
+ "MKK", "20M", "CCK", "1T", "13", "32",
+ "FCC", "20M", "CCK", "1T", "14", "63",
+ "ETSI", "20M", "CCK", "1T", "14", "63",
+ "MKK", "20M", "CCK", "1T", "14", "32",
+ "FCC", "20M", "OFDM", "1T", "01", "28",
+ "ETSI", "20M", "OFDM", "1T", "01", "32",
+ "MKK", "20M", "OFDM", "1T", "01", "32",
+ "FCC", "20M", "OFDM", "1T", "02", "28",
+ "ETSI", "20M", "OFDM", "1T", "02", "32",
+ "MKK", "20M", "OFDM", "1T", "02", "32",
+ "FCC", "20M", "OFDM", "1T", "03", "32",
+ "ETSI", "20M", "OFDM", "1T", "03", "32",
+ "MKK", "20M", "OFDM", "1T", "03", "32",
+ "FCC", "20M", "OFDM", "1T", "04", "32",
+ "ETSI", "20M", "OFDM", "1T", "04", "32",
+ "MKK", "20M", "OFDM", "1T", "04", "32",
+ "FCC", "20M", "OFDM", "1T", "05", "32",
+ "ETSI", "20M", "OFDM", "1T", "05", "32",
+ "MKK", "20M", "OFDM", "1T", "05", "32",
+ "FCC", "20M", "OFDM", "1T", "06", "32",
+ "ETSI", "20M", "OFDM", "1T", "06", "32",
+ "MKK", "20M", "OFDM", "1T", "06", "32",
+ "FCC", "20M", "OFDM", "1T", "07", "32",
+ "ETSI", "20M", "OFDM", "1T", "07", "32",
+ "MKK", "20M", "OFDM", "1T", "07", "32",
+ "FCC", "20M", "OFDM", "1T", "08", "32",
+ "ETSI", "20M", "OFDM", "1T", "08", "32",
+ "MKK", "20M", "OFDM", "1T", "08", "32",
+ "FCC", "20M", "OFDM", "1T", "09", "32",
+ "ETSI", "20M", "OFDM", "1T", "09", "32",
+ "MKK", "20M", "OFDM", "1T", "09", "32",
+ "FCC", "20M", "OFDM", "1T", "10", "28",
+ "ETSI", "20M", "OFDM", "1T", "10", "32",
+ "MKK", "20M", "OFDM", "1T", "10", "32",
+ "FCC", "20M", "OFDM", "1T", "11", "28",
+ "ETSI", "20M", "OFDM", "1T", "11", "32",
+ "MKK", "20M", "OFDM", "1T", "11", "32",
+ "FCC", "20M", "OFDM", "1T", "12", "63",
+ "ETSI", "20M", "OFDM", "1T", "12", "32",
+ "MKK", "20M", "OFDM", "1T", "12", "32",
+ "FCC", "20M", "OFDM", "1T", "13", "63",
+ "ETSI", "20M", "OFDM", "1T", "13", "32",
+ "MKK", "20M", "OFDM", "1T", "13", "32",
+ "FCC", "20M", "OFDM", "1T", "14", "63",
+ "ETSI", "20M", "OFDM", "1T", "14", "63",
+ "MKK", "20M", "OFDM", "1T", "14", "63",
+ "FCC", "20M", "HT", "1T", "01", "26",
+ "ETSI", "20M", "HT", "1T", "01", "32",
+ "MKK", "20M", "HT", "1T", "01", "32",
+ "FCC", "20M", "HT", "1T", "02", "26",
+ "ETSI", "20M", "HT", "1T", "02", "32",
+ "MKK", "20M", "HT", "1T", "02", "32",
+ "FCC", "20M", "HT", "1T", "03", "32",
+ "ETSI", "20M", "HT", "1T", "03", "32",
+ "MKK", "20M", "HT", "1T", "03", "32",
+ "FCC", "20M", "HT", "1T", "04", "32",
+ "ETSI", "20M", "HT", "1T", "04", "32",
+ "MKK", "20M", "HT", "1T", "04", "32",
+ "FCC", "20M", "HT", "1T", "05", "32",
+ "ETSI", "20M", "HT", "1T", "05", "32",
+ "MKK", "20M", "HT", "1T", "05", "32",
+ "FCC", "20M", "HT", "1T", "06", "32",
+ "ETSI", "20M", "HT", "1T", "06", "32",
+ "MKK", "20M", "HT", "1T", "06", "32",
+ "FCC", "20M", "HT", "1T", "07", "32",
+ "ETSI", "20M", "HT", "1T", "07", "32",
+ "MKK", "20M", "HT", "1T", "07", "32",
+ "FCC", "20M", "HT", "1T", "08", "32",
+ "ETSI", "20M", "HT", "1T", "08", "32",
+ "MKK", "20M", "HT", "1T", "08", "32",
+ "FCC", "20M", "HT", "1T", "09", "32",
+ "ETSI", "20M", "HT", "1T", "09", "32",
+ "MKK", "20M", "HT", "1T", "09", "32",
+ "FCC", "20M", "HT", "1T", "10", "26",
+ "ETSI", "20M", "HT", "1T", "10", "32",
+ "MKK", "20M", "HT", "1T", "10", "32",
+ "FCC", "20M", "HT", "1T", "11", "26",
+ "ETSI", "20M", "HT", "1T", "11", "32",
+ "MKK", "20M", "HT", "1T", "11", "32",
+ "FCC", "20M", "HT", "1T", "12", "63",
+ "ETSI", "20M", "HT", "1T", "12", "32",
+ "MKK", "20M", "HT", "1T", "12", "32",
+ "FCC", "20M", "HT", "1T", "13", "63",
+ "ETSI", "20M", "HT", "1T", "13", "32",
+ "MKK", "20M", "HT", "1T", "13", "32",
+ "FCC", "20M", "HT", "1T", "14", "63",
+ "ETSI", "20M", "HT", "1T", "14", "63",
+ "MKK", "20M", "HT", "1T", "14", "63",
+ "FCC", "40M", "HT", "1T", "01", "63",
+ "ETSI", "40M", "HT", "1T", "01", "63",
+ "MKK", "40M", "HT", "1T", "01", "63",
+ "FCC", "40M", "HT", "1T", "02", "63",
+ "ETSI", "40M", "HT", "1T", "02", "63",
+ "MKK", "40M", "HT", "1T", "02", "63",
+ "FCC", "40M", "HT", "1T", "03", "26",
+ "ETSI", "40M", "HT", "1T", "03", "32",
+ "MKK", "40M", "HT", "1T", "03", "32",
+ "FCC", "40M", "HT", "1T", "04", "26",
+ "ETSI", "40M", "HT", "1T", "04", "32",
+ "MKK", "40M", "HT", "1T", "04", "32",
+ "FCC", "40M", "HT", "1T", "05", "32",
+ "ETSI", "40M", "HT", "1T", "05", "32",
+ "MKK", "40M", "HT", "1T", "05", "32",
+ "FCC", "40M", "HT", "1T", "06", "32",
+ "ETSI", "40M", "HT", "1T", "06", "32",
+ "MKK", "40M", "HT", "1T", "06", "32",
+ "FCC", "40M", "HT", "1T", "07", "32",
+ "ETSI", "40M", "HT", "1T", "07", "32",
+ "MKK", "40M", "HT", "1T", "07", "32",
+ "FCC", "40M", "HT", "1T", "08", "26",
+ "ETSI", "40M", "HT", "1T", "08", "32",
+ "MKK", "40M", "HT", "1T", "08", "32",
+ "FCC", "40M", "HT", "1T", "09", "26",
+ "ETSI", "40M", "HT", "1T", "09", "32",
+ "MKK", "40M", "HT", "1T", "09", "32",
+ "FCC", "40M", "HT", "1T", "10", "26",
+ "ETSI", "40M", "HT", "1T", "10", "32",
+ "MKK", "40M", "HT", "1T", "10", "32",
+ "FCC", "40M", "HT", "1T", "11", "26",
+ "ETSI", "40M", "HT", "1T", "11", "32",
+ "MKK", "40M", "HT", "1T", "11", "32",
+ "FCC", "40M", "HT", "1T", "12", "63",
+ "ETSI", "40M", "HT", "1T", "12", "32",
+ "MKK", "40M", "HT", "1T", "12", "32",
+ "FCC", "40M", "HT", "1T", "13", "63",
+ "ETSI", "40M", "HT", "1T", "13", "32",
+ "MKK", "40M", "HT", "1T", "13", "32",
+ "FCC", "40M", "HT", "1T", "14", "63",
+ "ETSI", "40M", "HT", "1T", "14", "63",
+ "MKK", "40M", "HT", "1T", "14", "63"
+};
+
+void ODM_ReadAndConfig_MP_8723B_TXPWR_LMT(struct dm_odm_t *pDM_Odm)
+{
+ u32 i = 0;
+ u8 **Array = Array_MP_8723B_TXPWR_LMT;
+
+ for (i = 0; i < ARRAY_SIZE(Array_MP_8723B_TXPWR_LMT); i += 6) {
+ u8 *regulation = Array[i];
+ u8 *bandwidth = Array[i+1];
+ u8 *rate = Array[i+2];
+ u8 *rfPath = Array[i+3];
+ u8 *chnl = Array[i+4];
+ u8 *val = Array[i+5];
+
+ odm_ConfigBB_TXPWR_LMT_8723B(
+ pDM_Odm,
+ regulation,
+ bandwidth,
+ rate,
+ rfPath,
+ chnl,
+ val
+ );
+ }
+}
diff --git a/drivers/staging/rtl8723bs/hal/HalHWImg8723B_RF.h b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_RF.h
new file mode 100644
index 000000000..acf5679d1
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_RF.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+*
+* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+*
+******************************************************************************/
+
+#ifndef __INC_MP_RF_HW_IMG_8723B_H
+#define __INC_MP_RF_HW_IMG_8723B_H
+
+
+/******************************************************************************
+* RadioA.TXT
+******************************************************************************/
+
+void
+ODM_ReadAndConfig_MP_8723B_RadioA(/* TC: Test Chip, MP: MP Chip */
+ struct dm_odm_t *pDM_Odm
+);
+
+/******************************************************************************
+* TxPowerTrack_SDIO.TXT
+******************************************************************************/
+
+void
+ODM_ReadAndConfig_MP_8723B_TxPowerTrack_SDIO(/* TC: Test Chip, MP: MP Chip */
+ struct dm_odm_t *pDM_Odm
+);
+u32 ODM_GetVersion_MP_8723B_TxPowerTrack_SDIO(void);
+
+/******************************************************************************
+* TXPWR_LMT.TXT
+******************************************************************************/
+
+void
+ODM_ReadAndConfig_MP_8723B_TXPWR_LMT(/* TC: Test Chip, MP: MP Chip */
+ struct dm_odm_t *pDM_Odm
+);
+u32 ODM_GetVersion_MP_8723B_TXPWR_LMT(void);
+
+#endif
diff --git a/drivers/staging/rtl8723bs/hal/HalPhyRf.c b/drivers/staging/rtl8723bs/hal/HalPhyRf.c
new file mode 100644
index 000000000..7bef05a9a
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/HalPhyRf.c
@@ -0,0 +1,273 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+/* include "Mp_Precomp.h" */
+#include "odm_precomp.h"
+
+void ConfigureTxpowerTrack(struct dm_odm_t *pDM_Odm, struct txpwrtrack_cfg *pConfig)
+{
+ ConfigureTxpowerTrack_8723B(pConfig);
+}
+
+/* */
+/* <20121113, Kordan> This function should be called when TxAGC changed. */
+/* Otherwise the previous compensation is gone, because we record the */
+/* delta of temperature between two TxPowerTracking watch dogs. */
+/* */
+/* NOTE: If Tx BB swing or Tx scaling is varified during run-time, still */
+/* need to call this function. */
+/* */
+void ODM_ClearTxPowerTrackingState(struct dm_odm_t *pDM_Odm)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(pDM_Odm->Adapter);
+ u8 p = 0;
+
+ pDM_Odm->BbSwingIdxCckBase = pDM_Odm->DefaultCckIndex;
+ pDM_Odm->BbSwingIdxCck = pDM_Odm->DefaultCckIndex;
+ pDM_Odm->RFCalibrateInfo.CCK_index = 0;
+
+ for (p = RF_PATH_A; p < MAX_RF_PATH; ++p) {
+ pDM_Odm->BbSwingIdxOfdmBase[p] = pDM_Odm->DefaultOfdmIndex;
+ pDM_Odm->BbSwingIdxOfdm[p] = pDM_Odm->DefaultOfdmIndex;
+ pDM_Odm->RFCalibrateInfo.OFDM_index[p] = pDM_Odm->DefaultOfdmIndex;
+
+ pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p] = 0;
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[p] = 0;
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[p] = 0;
+ pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p] = 0;
+
+ /* Initial Mix mode power tracking */
+ pDM_Odm->Absolute_OFDMSwingIdx[p] = 0;
+ pDM_Odm->Remnant_OFDMSwingIdx[p] = 0;
+ }
+
+ /* Initial at Modify Tx Scaling Mode */
+ pDM_Odm->Modify_TxAGC_Flag_PathA = false;
+ /* Initial at Modify Tx Scaling Mode */
+ pDM_Odm->Modify_TxAGC_Flag_PathB = false;
+ pDM_Odm->Remnant_CCKSwingIdx = 0;
+ pDM_Odm->RFCalibrateInfo.ThermalValue = pHalData->EEPROMThermalMeter;
+ pDM_Odm->RFCalibrateInfo.ThermalValue_IQK = pHalData->EEPROMThermalMeter;
+ pDM_Odm->RFCalibrateInfo.ThermalValue_LCK = pHalData->EEPROMThermalMeter;
+}
+
+void ODM_TXPowerTrackingCallback_ThermalMeter(struct adapter *Adapter)
+{
+
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+ struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
+
+ u8 ThermalValue = 0, delta, delta_LCK, p = 0, i = 0;
+ u8 ThermalValue_AVG_count = 0;
+ u32 ThermalValue_AVG = 0;
+
+ u8 OFDM_min_index = 0; /* OFDM BB Swing should be less than +3.0dB, which is required by Arthur */
+ u8 Indexforchannel = 0; /* GetRightChnlPlaceforIQK(pHalData->CurrentChannel) */
+
+ struct txpwrtrack_cfg c;
+
+
+ /* 4 1. The following TWO tables decide the final index of OFDM/CCK swing table. */
+ u8 *deltaSwingTableIdx_TUP_A;
+ u8 *deltaSwingTableIdx_TDOWN_A;
+ u8 *deltaSwingTableIdx_TUP_B;
+ u8 *deltaSwingTableIdx_TDOWN_B;
+
+ /* 4 2. Initialization (7 steps in total) */
+
+ ConfigureTxpowerTrack(pDM_Odm, &c);
+
+ (*c.GetDeltaSwingTable)(
+ pDM_Odm,
+ (u8 **)&deltaSwingTableIdx_TUP_A,
+ (u8 **)&deltaSwingTableIdx_TDOWN_A,
+ (u8 **)&deltaSwingTableIdx_TUP_B,
+ (u8 **)&deltaSwingTableIdx_TDOWN_B
+ );
+
+ /* cosa add for debug */
+ pDM_Odm->RFCalibrateInfo.TXPowerTrackingCallbackCnt++;
+ pDM_Odm->RFCalibrateInfo.bTXPowerTrackingInit = true;
+
+ ThermalValue = (u8)PHY_QueryRFReg(pDM_Odm->Adapter, RF_PATH_A, c.ThermalRegAddr, 0xfc00); /* 0x42: RF Reg[15:10] 88E */
+ if (
+ !pDM_Odm->RFCalibrateInfo.TxPowerTrackControl ||
+ pHalData->EEPROMThermalMeter == 0 ||
+ pHalData->EEPROMThermalMeter == 0xFF
+ )
+ return;
+
+ /* 4 3. Initialize ThermalValues of RFCalibrateInfo */
+
+ /* 4 4. Calculate average thermal meter */
+
+ pDM_Odm->RFCalibrateInfo.ThermalValue_AVG[pDM_Odm->RFCalibrateInfo.ThermalValue_AVG_index] = ThermalValue;
+ pDM_Odm->RFCalibrateInfo.ThermalValue_AVG_index++;
+ if (pDM_Odm->RFCalibrateInfo.ThermalValue_AVG_index == c.AverageThermalNum) /* Average times = c.AverageThermalNum */
+ pDM_Odm->RFCalibrateInfo.ThermalValue_AVG_index = 0;
+
+ for (i = 0; i < c.AverageThermalNum; i++) {
+ if (pDM_Odm->RFCalibrateInfo.ThermalValue_AVG[i]) {
+ ThermalValue_AVG += pDM_Odm->RFCalibrateInfo.ThermalValue_AVG[i];
+ ThermalValue_AVG_count++;
+ }
+ }
+
+ /* Calculate Average ThermalValue after average enough times */
+ if (ThermalValue_AVG_count) {
+ ThermalValue = (u8)(ThermalValue_AVG / ThermalValue_AVG_count);
+ }
+
+ /* 4 5. Calculate delta, delta_LCK */
+ /* delta" here is used to determine whether thermal value changes or not. */
+ delta =
+ (ThermalValue > pDM_Odm->RFCalibrateInfo.ThermalValue) ?
+ (ThermalValue - pDM_Odm->RFCalibrateInfo.ThermalValue) :
+ (pDM_Odm->RFCalibrateInfo.ThermalValue - ThermalValue);
+ delta_LCK =
+ (ThermalValue > pDM_Odm->RFCalibrateInfo.ThermalValue_LCK) ?
+ (ThermalValue - pDM_Odm->RFCalibrateInfo.ThermalValue_LCK) :
+ (pDM_Odm->RFCalibrateInfo.ThermalValue_LCK - ThermalValue);
+
+ /* 4 6. If necessary, do LCK. */
+ /* Delta temperature is equal to or larger than 20 centigrade. */
+ if (delta_LCK >= c.Threshold_IQK) {
+ pDM_Odm->RFCalibrateInfo.ThermalValue_LCK = ThermalValue;
+ if (c.PHY_LCCalibrate)
+ (*c.PHY_LCCalibrate)(pDM_Odm);
+ }
+
+ /* 3 7. If necessary, move the index of swing table to adjust Tx power. */
+ if (delta > 0 && pDM_Odm->RFCalibrateInfo.TxPowerTrackControl) {
+ /* delta" here is used to record the absolute value of difference. */
+ delta =
+ ThermalValue > pHalData->EEPROMThermalMeter ?
+ (ThermalValue - pHalData->EEPROMThermalMeter) :
+ (pHalData->EEPROMThermalMeter - ThermalValue);
+
+ if (delta >= TXPWR_TRACK_TABLE_SIZE)
+ delta = TXPWR_TRACK_TABLE_SIZE - 1;
+
+ /* 4 7.1 The Final Power Index = BaseIndex + PowerIndexOffset */
+ if (ThermalValue > pHalData->EEPROMThermalMeter) {
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[RF_PATH_A] =
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[RF_PATH_A];
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[RF_PATH_A] =
+ deltaSwingTableIdx_TUP_A[delta];
+
+ /* Record delta swing for mix mode power tracking */
+ pDM_Odm->Absolute_OFDMSwingIdx[RF_PATH_A] =
+ deltaSwingTableIdx_TUP_A[delta];
+
+ if (c.RfPathCount > 1) {
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[RF_PATH_B] =
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[RF_PATH_B];
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[RF_PATH_B] =
+ deltaSwingTableIdx_TUP_B[delta];
+
+ /* Record delta swing for mix mode power tracking */
+ pDM_Odm->Absolute_OFDMSwingIdx[RF_PATH_B] =
+ deltaSwingTableIdx_TUP_B[delta];
+ }
+
+ } else {
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[RF_PATH_A] =
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[RF_PATH_A];
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[RF_PATH_A] =
+ -1 * deltaSwingTableIdx_TDOWN_A[delta];
+
+ /* Record delta swing for mix mode power tracking */
+ pDM_Odm->Absolute_OFDMSwingIdx[RF_PATH_A] =
+ -1 * deltaSwingTableIdx_TDOWN_A[delta];
+
+ if (c.RfPathCount > 1) {
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[RF_PATH_B] =
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[RF_PATH_B];
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[RF_PATH_B] =
+ -1 * deltaSwingTableIdx_TDOWN_B[delta];
+
+ /* Record delta swing for mix mode power tracking */
+ pDM_Odm->Absolute_OFDMSwingIdx[RF_PATH_B] =
+ -1 * deltaSwingTableIdx_TDOWN_B[delta];
+ }
+ }
+
+ for (p = RF_PATH_A; p < c.RfPathCount; p++) {
+ if (
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[p] ==
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[p]
+ ) /* If Thermal value changes but lookup table value still the same */
+ pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p] = 0;
+ else
+ pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p] = pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[p] - pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[p]; /* Power Index Diff between 2 times Power Tracking */
+
+ pDM_Odm->RFCalibrateInfo.OFDM_index[p] =
+ pDM_Odm->BbSwingIdxOfdmBase[p] +
+ pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p];
+
+ pDM_Odm->RFCalibrateInfo.CCK_index =
+ pDM_Odm->BbSwingIdxCckBase +
+ pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p];
+
+ pDM_Odm->BbSwingIdxCck =
+ pDM_Odm->RFCalibrateInfo.CCK_index;
+
+ pDM_Odm->BbSwingIdxOfdm[p] =
+ pDM_Odm->RFCalibrateInfo.OFDM_index[p];
+
+ /* 4 7.1 Handle boundary conditions of index. */
+ if (pDM_Odm->RFCalibrateInfo.OFDM_index[p] > c.SwingTableSize_OFDM-1)
+ pDM_Odm->RFCalibrateInfo.OFDM_index[p] = c.SwingTableSize_OFDM-1;
+ else if (pDM_Odm->RFCalibrateInfo.OFDM_index[p] < OFDM_min_index)
+ pDM_Odm->RFCalibrateInfo.OFDM_index[p] = OFDM_min_index;
+ }
+ if (pDM_Odm->RFCalibrateInfo.CCK_index > c.SwingTableSize_CCK-1)
+ pDM_Odm->RFCalibrateInfo.CCK_index = c.SwingTableSize_CCK-1;
+ /* else if (pDM_Odm->RFCalibrateInfo.CCK_index < 0) */
+ /* pDM_Odm->RFCalibrateInfo.CCK_index = 0; */
+ } else {
+ for (p = RF_PATH_A; p < c.RfPathCount; p++)
+ pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p] = 0;
+ }
+
+ /* Print Swing base & current */
+ for (p = RF_PATH_A; p < c.RfPathCount; p++) {
+ }
+
+ if (
+ (pDM_Odm->RFCalibrateInfo.PowerIndexOffset[RF_PATH_A] != 0 ||
+ pDM_Odm->RFCalibrateInfo.PowerIndexOffset[RF_PATH_B] != 0) &&
+ pDM_Odm->RFCalibrateInfo.TxPowerTrackControl
+ ) {
+ /* 4 7.2 Configure the Swing Table to adjust Tx Power. */
+
+ pDM_Odm->RFCalibrateInfo.bTxPowerChanged = true; /* Always true after Tx Power is adjusted by power tracking. */
+ /* */
+ /* 2012/04/23 MH According to Luke's suggestion, we can not write BB digital */
+ /* to increase TX power. Otherwise, EVM will be bad. */
+ /* */
+ /* 2012/04/25 MH Add for tx power tracking to set tx power in tx agc for 88E. */
+
+ if (ThermalValue > pHalData->EEPROMThermalMeter) {
+ for (p = RF_PATH_A; p < c.RfPathCount; p++)
+ (*c.ODM_TxPwrTrackSetPwr)(pDM_Odm, MIX_MODE, p, 0);
+ } else {
+ for (p = RF_PATH_A; p < c.RfPathCount; p++)
+ (*c.ODM_TxPwrTrackSetPwr)(pDM_Odm, MIX_MODE, p, Indexforchannel);
+ }
+
+ /* Record last time Power Tracking result as base. */
+ pDM_Odm->BbSwingIdxCckBase = pDM_Odm->BbSwingIdxCck;
+ for (p = RF_PATH_A; p < c.RfPathCount; p++)
+ pDM_Odm->BbSwingIdxOfdmBase[p] = pDM_Odm->BbSwingIdxOfdm[p];
+
+ /* Record last Power Tracking Thermal Value */
+ pDM_Odm->RFCalibrateInfo.ThermalValue = ThermalValue;
+ }
+
+ pDM_Odm->RFCalibrateInfo.TXPowercount = 0;
+}
diff --git a/drivers/staging/rtl8723bs/hal/HalPhyRf.h b/drivers/staging/rtl8723bs/hal/HalPhyRf.h
new file mode 100644
index 000000000..fdbdd68ed
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/HalPhyRf.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+ #ifndef __HAL_PHY_RF_H__
+ #define __HAL_PHY_RF_H__
+
+enum pwrtrack_method {
+ BBSWING,
+ TXAGC,
+ MIX_MODE
+};
+
+typedef void (*FuncSetPwr)(struct dm_odm_t *, enum pwrtrack_method, u8, u8);
+typedef void (*FuncIQK)(struct dm_odm_t *, u8, u8, u8);
+typedef void (*FuncLCK)(struct dm_odm_t *);
+typedef void (*FuncSwing)(struct dm_odm_t *, u8 **, u8 **, u8 **, u8 **);
+
+struct txpwrtrack_cfg {
+ u8 SwingTableSize_CCK;
+ u8 SwingTableSize_OFDM;
+ u8 Threshold_IQK;
+ u8 AverageThermalNum;
+ u8 RfPathCount;
+ u32 ThermalRegAddr;
+ FuncSetPwr ODM_TxPwrTrackSetPwr;
+ FuncIQK DoIQK;
+ FuncLCK PHY_LCCalibrate;
+ FuncSwing GetDeltaSwingTable;
+};
+
+void ConfigureTxpowerTrack(struct dm_odm_t *pDM_Odm, struct txpwrtrack_cfg *pConfig);
+
+
+void ODM_ClearTxPowerTrackingState(struct dm_odm_t *pDM_Odm);
+
+void ODM_TXPowerTrackingCallback_ThermalMeter(struct adapter *Adapter);
+
+#endif /* #ifndef __HAL_PHY_RF_H__ */
diff --git a/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c b/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c
new file mode 100644
index 000000000..a52748f7b
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c
@@ -0,0 +1,1822 @@
+// SPDX-License-Identifier: GPL-2.0
+/*****************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include <drv_types.h>
+#include <rtw_debug.h>
+#include "odm_precomp.h"
+
+/* MACRO definition for pRFCalibrateInfo->TxIQC_8723B[0] */
+#define PATH_S0 1 /* RF_PATH_B */
+#define IDX_0xC94 0
+#define IDX_0xC80 1
+#define IDX_0xC14 0
+#define IDX_0xCA0 1
+#define KEY 0
+#define VAL 1
+
+/* MACRO definition for pRFCalibrateInfo->TxIQC_8723B[1] */
+#define PATH_S1 0 /* RF_PATH_A */
+#define IDX_0xC4C 2
+
+/*---------------------------Define Local Constant---------------------------*/
+
+/* In the case that we fail to read TxPowerTrack.txt, we use the table for
+ * 88E as the default table.
+ */
+static u8 DeltaSwingTableIdx_2GA_N_8188E[] = {
+ 0, 0, 0, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6,
+ 7, 7, 7, 7, 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, 11
+};
+static u8 DeltaSwingTableIdx_2GA_P_8188E[] = {
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 4,
+ 4, 4, 4, 5, 5, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9
+};
+
+/* 3 ============================================================ */
+/* 3 Tx Power Tracking */
+/* 3 ============================================================ */
+
+
+static void setIqkMatrix_8723B(
+ struct dm_odm_t *pDM_Odm,
+ u8 OFDM_index,
+ u8 RFPath,
+ s32 IqkResult_X,
+ s32 IqkResult_Y
+)
+{
+ s32 ele_A = 0, ele_D, ele_C = 0, value32;
+
+ if (OFDM_index >= OFDM_TABLE_SIZE)
+ OFDM_index = OFDM_TABLE_SIZE-1;
+
+ ele_D = (OFDMSwingTable_New[OFDM_index] & 0xFFC00000)>>22;
+
+ /* new element A = element D x X */
+ if (IqkResult_X != 0) {
+ if ((IqkResult_X & 0x00000200) != 0) /* consider minus */
+ IqkResult_X = IqkResult_X | 0xFFFFFC00;
+ ele_A = ((IqkResult_X * ele_D)>>8)&0x000003FF;
+
+ /* new element C = element D x Y */
+ if ((IqkResult_Y & 0x00000200) != 0)
+ IqkResult_Y = IqkResult_Y | 0xFFFFFC00;
+ ele_C = ((IqkResult_Y * ele_D)>>8)&0x000003FF;
+
+ /* if (RFPath == RF_PATH_A) */
+ switch (RFPath) {
+ case RF_PATH_A:
+ /* write new elements A, C, D to regC80 and regC94,
+ * element B is always 0
+ */
+ value32 = (ele_D<<22)|((ele_C&0x3F)<<16)|ele_A;
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XATxIQImbalance, bMaskDWord, value32);
+
+ value32 = (ele_C&0x000003C0)>>6;
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XCTxAFE, bMaskH4Bits, value32);
+
+ value32 = ((IqkResult_X * ele_D)>>7)&0x01;
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, BIT24, value32);
+ break;
+ case RF_PATH_B:
+ /* write new elements A, C, D to regC88 and regC9C,
+ * element B is always 0
+ */
+ value32 = (ele_D<<22)|((ele_C&0x3F)<<16)|ele_A;
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XBTxIQImbalance, bMaskDWord, value32);
+
+ value32 = (ele_C&0x000003C0)>>6;
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XDTxAFE, bMaskH4Bits, value32);
+
+ value32 = ((IqkResult_X * ele_D)>>7)&0x01;
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, BIT28, value32);
+
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch (RFPath) {
+ case RF_PATH_A:
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XATxIQImbalance, bMaskDWord, OFDMSwingTable_New[OFDM_index]);
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XCTxAFE, bMaskH4Bits, 0x00);
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, BIT24, 0x00);
+ break;
+
+ case RF_PATH_B:
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XBTxIQImbalance, bMaskDWord, OFDMSwingTable_New[OFDM_index]);
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XDTxAFE, bMaskH4Bits, 0x00);
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, BIT28, 0x00);
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+
+static void setCCKFilterCoefficient(struct dm_odm_t *pDM_Odm, u8 CCKSwingIndex)
+{
+ if (!pDM_Odm->RFCalibrateInfo.bCCKinCH14) {
+ rtw_write8(pDM_Odm->Adapter, 0xa22, CCKSwingTable_Ch1_Ch13_New[CCKSwingIndex][0]);
+ rtw_write8(pDM_Odm->Adapter, 0xa23, CCKSwingTable_Ch1_Ch13_New[CCKSwingIndex][1]);
+ rtw_write8(pDM_Odm->Adapter, 0xa24, CCKSwingTable_Ch1_Ch13_New[CCKSwingIndex][2]);
+ rtw_write8(pDM_Odm->Adapter, 0xa25, CCKSwingTable_Ch1_Ch13_New[CCKSwingIndex][3]);
+ rtw_write8(pDM_Odm->Adapter, 0xa26, CCKSwingTable_Ch1_Ch13_New[CCKSwingIndex][4]);
+ rtw_write8(pDM_Odm->Adapter, 0xa27, CCKSwingTable_Ch1_Ch13_New[CCKSwingIndex][5]);
+ rtw_write8(pDM_Odm->Adapter, 0xa28, CCKSwingTable_Ch1_Ch13_New[CCKSwingIndex][6]);
+ rtw_write8(pDM_Odm->Adapter, 0xa29, CCKSwingTable_Ch1_Ch13_New[CCKSwingIndex][7]);
+ } else {
+ rtw_write8(pDM_Odm->Adapter, 0xa22, CCKSwingTable_Ch14_New[CCKSwingIndex][0]);
+ rtw_write8(pDM_Odm->Adapter, 0xa23, CCKSwingTable_Ch14_New[CCKSwingIndex][1]);
+ rtw_write8(pDM_Odm->Adapter, 0xa24, CCKSwingTable_Ch14_New[CCKSwingIndex][2]);
+ rtw_write8(pDM_Odm->Adapter, 0xa25, CCKSwingTable_Ch14_New[CCKSwingIndex][3]);
+ rtw_write8(pDM_Odm->Adapter, 0xa26, CCKSwingTable_Ch14_New[CCKSwingIndex][4]);
+ rtw_write8(pDM_Odm->Adapter, 0xa27, CCKSwingTable_Ch14_New[CCKSwingIndex][5]);
+ rtw_write8(pDM_Odm->Adapter, 0xa28, CCKSwingTable_Ch14_New[CCKSwingIndex][6]);
+ rtw_write8(pDM_Odm->Adapter, 0xa29, CCKSwingTable_Ch14_New[CCKSwingIndex][7]);
+ }
+}
+
+void DoIQK_8723B(
+ struct dm_odm_t *pDM_Odm,
+ u8 DeltaThermalIndex,
+ u8 ThermalValue,
+ u8 Threshold
+)
+{
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: odm_TxPwrTrackSetPwr88E()
+ *
+ * Overview: 88E change all channel tx power according to flag.
+ * OFDM & CCK are all different.
+ *
+ * Input: NONE
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ *
+ * Revised History:
+ *When Who Remark
+ *04/23/2012 MHC Create Version 0.
+ *
+ *---------------------------------------------------------------------------*/
+void ODM_TxPwrTrackSetPwr_8723B(
+ struct dm_odm_t *pDM_Odm,
+ enum pwrtrack_method Method,
+ u8 RFPath,
+ u8 ChannelMappedIndex
+)
+{
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+ u8 PwrTrackingLimit_OFDM = 34; /* 0dB */
+ u8 PwrTrackingLimit_CCK = 28; /* 2dB */
+ u8 TxRate = 0xFF;
+ u8 Final_OFDM_Swing_Index = 0;
+ u8 Final_CCK_Swing_Index = 0;
+
+ {
+ u16 rate = *(pDM_Odm->pForcedDataRate);
+
+ if (!rate) { /* auto rate */
+ if (pDM_Odm->TxRate != 0xFF)
+ TxRate = HwRateToMRate(pDM_Odm->TxRate);
+ } else /* force rate */
+ TxRate = (u8)rate;
+
+ }
+
+ if (TxRate != 0xFF) {
+ /* 2 CCK */
+ if ((TxRate >= MGN_1M) && (TxRate <= MGN_11M))
+ PwrTrackingLimit_CCK = 28; /* 2dB */
+ /* 2 OFDM */
+ else if ((TxRate >= MGN_6M) && (TxRate <= MGN_48M))
+ PwrTrackingLimit_OFDM = 36; /* 3dB */
+ else if (TxRate == MGN_54M)
+ PwrTrackingLimit_OFDM = 34; /* 2dB */
+
+ /* 2 HT */
+ else if ((TxRate >= MGN_MCS0) && (TxRate <= MGN_MCS2)) /* QPSK/BPSK */
+ PwrTrackingLimit_OFDM = 38; /* 4dB */
+ else if ((TxRate >= MGN_MCS3) && (TxRate <= MGN_MCS4)) /* 16QAM */
+ PwrTrackingLimit_OFDM = 36; /* 3dB */
+ else if ((TxRate >= MGN_MCS5) && (TxRate <= MGN_MCS7)) /* 64QAM */
+ PwrTrackingLimit_OFDM = 34; /* 2dB */
+
+ else
+ PwrTrackingLimit_OFDM = pDM_Odm->DefaultOfdmIndex; /* Default OFDM index = 30 */
+ }
+
+ if (Method == TXAGC) {
+ struct adapter *Adapter = pDM_Odm->Adapter;
+
+ pDM_Odm->Remnant_OFDMSwingIdx[RFPath] = pDM_Odm->Absolute_OFDMSwingIdx[RFPath];
+
+ pDM_Odm->Modify_TxAGC_Flag_PathA = true;
+ pDM_Odm->Modify_TxAGC_Flag_PathA_CCK = true;
+
+ PHY_SetTxPowerIndexByRateSection(Adapter, RFPath, pHalData->CurrentChannel, CCK);
+ PHY_SetTxPowerIndexByRateSection(Adapter, RFPath, pHalData->CurrentChannel, OFDM);
+ PHY_SetTxPowerIndexByRateSection(Adapter, RFPath, pHalData->CurrentChannel, HT_MCS0_MCS7);
+ } else if (Method == BBSWING) {
+ Final_OFDM_Swing_Index = pDM_Odm->DefaultOfdmIndex + pDM_Odm->Absolute_OFDMSwingIdx[RFPath];
+ Final_CCK_Swing_Index = pDM_Odm->DefaultCckIndex + pDM_Odm->Absolute_OFDMSwingIdx[RFPath];
+
+ /* Adjust BB swing by OFDM IQ matrix */
+ if (Final_OFDM_Swing_Index >= PwrTrackingLimit_OFDM)
+ Final_OFDM_Swing_Index = PwrTrackingLimit_OFDM;
+ else if (Final_OFDM_Swing_Index <= 0)
+ Final_OFDM_Swing_Index = 0;
+
+ if (Final_CCK_Swing_Index >= CCK_TABLE_SIZE)
+ Final_CCK_Swing_Index = CCK_TABLE_SIZE-1;
+ else if (pDM_Odm->BbSwingIdxCck <= 0)
+ Final_CCK_Swing_Index = 0;
+
+ setIqkMatrix_8723B(pDM_Odm, Final_OFDM_Swing_Index, RFPath,
+ pDM_Odm->RFCalibrateInfo.IQKMatrixRegSetting[ChannelMappedIndex].Value[0][0],
+ pDM_Odm->RFCalibrateInfo.IQKMatrixRegSetting[ChannelMappedIndex].Value[0][1]);
+
+ setCCKFilterCoefficient(pDM_Odm, Final_CCK_Swing_Index);
+
+ } else if (Method == MIX_MODE) {
+ Final_OFDM_Swing_Index = pDM_Odm->DefaultOfdmIndex + pDM_Odm->Absolute_OFDMSwingIdx[RFPath];
+ Final_CCK_Swing_Index = pDM_Odm->DefaultCckIndex + pDM_Odm->Absolute_OFDMSwingIdx[RFPath];
+
+ if (Final_OFDM_Swing_Index > PwrTrackingLimit_OFDM) { /* BBSwing higher then Limit */
+ pDM_Odm->Remnant_OFDMSwingIdx[RFPath] = Final_OFDM_Swing_Index - PwrTrackingLimit_OFDM;
+
+ setIqkMatrix_8723B(pDM_Odm, PwrTrackingLimit_OFDM, RFPath,
+ pDM_Odm->RFCalibrateInfo.IQKMatrixRegSetting[ChannelMappedIndex].Value[0][0],
+ pDM_Odm->RFCalibrateInfo.IQKMatrixRegSetting[ChannelMappedIndex].Value[0][1]);
+
+ pDM_Odm->Modify_TxAGC_Flag_PathA = true;
+ PHY_SetTxPowerIndexByRateSection(Adapter, RFPath, pHalData->CurrentChannel, OFDM);
+ PHY_SetTxPowerIndexByRateSection(Adapter, RFPath, pHalData->CurrentChannel, HT_MCS0_MCS7);
+ } else if (Final_OFDM_Swing_Index <= 0) {
+ pDM_Odm->Remnant_OFDMSwingIdx[RFPath] = Final_OFDM_Swing_Index;
+
+ setIqkMatrix_8723B(pDM_Odm, 0, RFPath,
+ pDM_Odm->RFCalibrateInfo.IQKMatrixRegSetting[ChannelMappedIndex].Value[0][0],
+ pDM_Odm->RFCalibrateInfo.IQKMatrixRegSetting[ChannelMappedIndex].Value[0][1]);
+
+ pDM_Odm->Modify_TxAGC_Flag_PathA = true;
+ PHY_SetTxPowerIndexByRateSection(Adapter, RFPath, pHalData->CurrentChannel, OFDM);
+ PHY_SetTxPowerIndexByRateSection(Adapter, RFPath, pHalData->CurrentChannel, HT_MCS0_MCS7);
+ } else {
+ setIqkMatrix_8723B(pDM_Odm, Final_OFDM_Swing_Index, RFPath,
+ pDM_Odm->RFCalibrateInfo.IQKMatrixRegSetting[ChannelMappedIndex].Value[0][0],
+ pDM_Odm->RFCalibrateInfo.IQKMatrixRegSetting[ChannelMappedIndex].Value[0][1]);
+
+ if (pDM_Odm->Modify_TxAGC_Flag_PathA) { /* If TxAGC has changed, reset TxAGC again */
+ pDM_Odm->Remnant_OFDMSwingIdx[RFPath] = 0;
+ PHY_SetTxPowerIndexByRateSection(Adapter, RFPath, pHalData->CurrentChannel, OFDM);
+ PHY_SetTxPowerIndexByRateSection(Adapter, RFPath, pHalData->CurrentChannel, HT_MCS0_MCS7);
+ pDM_Odm->Modify_TxAGC_Flag_PathA = false;
+ }
+ }
+
+ if (Final_CCK_Swing_Index > PwrTrackingLimit_CCK) {
+ pDM_Odm->Remnant_CCKSwingIdx = Final_CCK_Swing_Index - PwrTrackingLimit_CCK;
+ setCCKFilterCoefficient(pDM_Odm, PwrTrackingLimit_CCK);
+ pDM_Odm->Modify_TxAGC_Flag_PathA_CCK = true;
+ PHY_SetTxPowerIndexByRateSection(Adapter, RFPath, pHalData->CurrentChannel, CCK);
+ } else if (Final_CCK_Swing_Index <= 0) { /* Lowest CCK Index = 0 */
+ pDM_Odm->Remnant_CCKSwingIdx = Final_CCK_Swing_Index;
+ setCCKFilterCoefficient(pDM_Odm, 0);
+ pDM_Odm->Modify_TxAGC_Flag_PathA_CCK = true;
+ PHY_SetTxPowerIndexByRateSection(Adapter, RFPath, pHalData->CurrentChannel, CCK);
+ } else {
+ setCCKFilterCoefficient(pDM_Odm, Final_CCK_Swing_Index);
+
+ if (pDM_Odm->Modify_TxAGC_Flag_PathA_CCK) { /* If TxAGC has changed, reset TxAGC again */
+ pDM_Odm->Remnant_CCKSwingIdx = 0;
+ PHY_SetTxPowerIndexByRateSection(Adapter, RFPath, pHalData->CurrentChannel, CCK);
+ pDM_Odm->Modify_TxAGC_Flag_PathA_CCK = false;
+ }
+ }
+ } else
+ return; /* This method is not supported. */
+}
+
+static void GetDeltaSwingTable_8723B(
+ struct dm_odm_t *pDM_Odm,
+ u8 **TemperatureUP_A,
+ u8 **TemperatureDOWN_A,
+ u8 **TemperatureUP_B,
+ u8 **TemperatureDOWN_B
+)
+{
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ struct odm_rf_cal_t *pRFCalibrateInfo = &pDM_Odm->RFCalibrateInfo;
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+ u16 rate = *(pDM_Odm->pForcedDataRate);
+ u8 channel = pHalData->CurrentChannel;
+
+ if (1 <= channel && channel <= 14) {
+ if (IS_CCK_RATE(rate)) {
+ *TemperatureUP_A = pRFCalibrateInfo->DeltaSwingTableIdx_2GCCKA_P;
+ *TemperatureDOWN_A = pRFCalibrateInfo->DeltaSwingTableIdx_2GCCKA_N;
+ *TemperatureUP_B = pRFCalibrateInfo->DeltaSwingTableIdx_2GCCKB_P;
+ *TemperatureDOWN_B = pRFCalibrateInfo->DeltaSwingTableIdx_2GCCKB_N;
+ } else {
+ *TemperatureUP_A = pRFCalibrateInfo->DeltaSwingTableIdx_2GA_P;
+ *TemperatureDOWN_A = pRFCalibrateInfo->DeltaSwingTableIdx_2GA_N;
+ *TemperatureUP_B = pRFCalibrateInfo->DeltaSwingTableIdx_2GB_P;
+ *TemperatureDOWN_B = pRFCalibrateInfo->DeltaSwingTableIdx_2GB_N;
+ }
+ } else {
+ *TemperatureUP_A = (u8 *)DeltaSwingTableIdx_2GA_P_8188E;
+ *TemperatureDOWN_A = (u8 *)DeltaSwingTableIdx_2GA_N_8188E;
+ *TemperatureUP_B = (u8 *)DeltaSwingTableIdx_2GA_P_8188E;
+ *TemperatureDOWN_B = (u8 *)DeltaSwingTableIdx_2GA_N_8188E;
+ }
+}
+
+
+void ConfigureTxpowerTrack_8723B(struct txpwrtrack_cfg *pConfig)
+{
+ pConfig->SwingTableSize_CCK = CCK_TABLE_SIZE;
+ pConfig->SwingTableSize_OFDM = OFDM_TABLE_SIZE;
+ pConfig->Threshold_IQK = IQK_THRESHOLD;
+ pConfig->AverageThermalNum = AVG_THERMAL_NUM_8723B;
+ pConfig->RfPathCount = MAX_PATH_NUM_8723B;
+ pConfig->ThermalRegAddr = RF_T_METER_8723B;
+
+ pConfig->ODM_TxPwrTrackSetPwr = ODM_TxPwrTrackSetPwr_8723B;
+ pConfig->DoIQK = DoIQK_8723B;
+ pConfig->PHY_LCCalibrate = PHY_LCCalibrate_8723B;
+ pConfig->GetDeltaSwingTable = GetDeltaSwingTable_8723B;
+}
+
+/* 1 7. IQK */
+#define MAX_TOLERANCE 5
+
+/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */
+static u8 phy_PathA_IQK_8723B(
+ struct adapter *padapter, bool configPathB, u8 RF_Path
+)
+{
+ u32 regEAC, regE94, regE9C, tmp, Path_SEL_BB /*, regEA4*/;
+ u8 result = 0x00;
+
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
+
+ /* Save RF Path */
+ Path_SEL_BB = PHY_QueryBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord);
+
+ /* leave IQK mode */
+ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+
+ /* enable path A PA in TXIQK mode */
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0003f);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xc7f87);
+ /* disable path B PA in TXIQK mode */
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xed, bRFRegOffsetMask, 0x00020); */
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0x43, bRFRegOffsetMask, 0x40ec1); */
+
+ /* 1 Tx IQK */
+ /* IQK setting */
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK, bMaskDWord, 0x01007c00);
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK, bMaskDWord, 0x01004800);
+ /* path-A IQK setting */
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
+/* PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_A, bMaskDWord, 0x8214010a); */
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_A, bMaskDWord, 0x821303ea);
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_A, bMaskDWord, 0x28110000);
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_B, bMaskDWord, 0x82110000);
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_B, bMaskDWord, 0x28110000);
+
+ /* LO calibration setting */
+ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Rsp, bMaskDWord, 0x00462911);
+
+ /* enter IQK mode */
+ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x808000);
+
+ /* Ant switch */
+ if (configPathB || (RF_Path == 0))
+ /* wifi switch to S1 */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, 0x00000000);
+ else
+ /* wifi switch to S0 */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, 0x00000280);
+
+ /* GNT_BT = 0 */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00000800);
+
+ /* One shot, path A LOK & IQK */
+ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
+ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
+
+ /* delay x ms */
+ /* PlatformStallExecution(IQK_DELAY_TIME_8723B*1000); */
+ mdelay(IQK_DELAY_TIME_8723B);
+
+ /* restore Ant Path */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, Path_SEL_BB);
+ /* GNT_BT = 1 */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00001800);
+
+ /* leave IQK mode */
+ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+
+
+ /* Check failed */
+ regEAC = PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_After_IQK_A_2, bMaskDWord);
+ regE94 = PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_Before_IQK_A, bMaskDWord);
+ regE9C = PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_After_IQK_A, bMaskDWord);
+
+
+ /* Allen 20131125 */
+ tmp = (regE9C & 0x03FF0000)>>16;
+ if ((tmp & 0x200) > 0)
+ tmp = 0x400 - tmp;
+
+ if (
+ !(regEAC & BIT28) &&
+ (((regE94 & 0x03FF0000)>>16) != 0x142) &&
+ (((regE9C & 0x03FF0000)>>16) != 0x42) &&
+ (((regE94 & 0x03FF0000)>>16) < 0x110) &&
+ (((regE94 & 0x03FF0000)>>16) > 0xf0) &&
+ (tmp < 0xf)
+ )
+ result |= 0x01;
+ else /* if Tx not OK, ignore Rx */
+ return result;
+
+ return result;
+}
+
+/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */
+static u8 phy_PathA_RxIQK8723B(
+ struct adapter *padapter, bool configPathB, u8 RF_Path
+)
+{
+ u32 regEAC, regE94, regE9C, regEA4, u4tmp, tmp, Path_SEL_BB;
+ u8 result = 0x00;
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
+
+ /* Save RF Path */
+ Path_SEL_BB = PHY_QueryBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord);
+
+ /* leave IQK mode */
+ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+ /* 1 Get TXIMR setting */
+ /* modify RXIQK mode table */
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f);
+ /* LNA2 off, PA on for Dcut */
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7fb7);
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_WE_LUT, 0x80000, 0x0); */
+ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x808000);
+
+ /* IQK setting */
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK, bMaskDWord, 0x01007c00);
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK, bMaskDWord, 0x01004800);
+
+ /* path-A IQK setting */
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
+
+/* PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_A, bMaskDWord, 0x82160c1f); */
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_A, bMaskDWord, 0x82130ff0);
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_A, bMaskDWord, 0x28110000);
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_B, bMaskDWord, 0x82110000);
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_B, bMaskDWord, 0x28110000);
+
+ /* LO calibration setting */
+ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
+
+ /* enter IQK mode */
+ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x808000);
+
+ /* Ant switch */
+ if (configPathB || (RF_Path == 0))
+ /* wifi switch to S1 */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, 0x00000000);
+ else
+ /* wifi switch to S0 */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, 0x00000280);
+
+ /* GNT_BT = 0 */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00000800);
+
+ /* One shot, path A LOK & IQK */
+ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
+ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
+
+ /* delay x ms */
+ /* PlatformStallExecution(IQK_DELAY_TIME_8723B*1000); */
+ mdelay(IQK_DELAY_TIME_8723B);
+
+ /* restore Ant Path */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, Path_SEL_BB);
+ /* GNT_BT = 1 */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00001800);
+
+ /* leave IQK mode */
+ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+
+ /* Check failed */
+ regEAC = PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_After_IQK_A_2, bMaskDWord);
+ regE94 = PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_Before_IQK_A, bMaskDWord);
+ regE9C = PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_After_IQK_A, bMaskDWord);
+
+ /* Allen 20131125 */
+ tmp = (regE9C & 0x03FF0000)>>16;
+ if ((tmp & 0x200) > 0)
+ tmp = 0x400 - tmp;
+
+ if (
+ !(regEAC & BIT28) &&
+ (((regE94 & 0x03FF0000)>>16) != 0x142) &&
+ (((regE9C & 0x03FF0000)>>16) != 0x42) &&
+ (((regE94 & 0x03FF0000)>>16) < 0x110) &&
+ (((regE94 & 0x03FF0000)>>16) > 0xf0) &&
+ (tmp < 0xf)
+ )
+ result |= 0x01;
+ else /* if Tx not OK, ignore Rx */
+ return result;
+
+ u4tmp = 0x80007C00 | (regE94&0x3FF0000) | ((regE9C&0x3FF0000) >> 16);
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK, bMaskDWord, u4tmp);
+
+ /* modify RXIQK mode table */
+ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f);
+ /* LAN2 on, PA off for Dcut */
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7d77);
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_WE_LUT, 0x80000, 0x0); */
+
+ /* PA, PAD setting */
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0xf80);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0x55, bRFRegOffsetMask, 0x4021f);
+
+
+ /* IQK setting */
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK, bMaskDWord, 0x01004800);
+
+ /* path-A IQK setting */
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
+
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_A, bMaskDWord, 0x82110000);
+/* PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_A, bMaskDWord, 0x281604c2); */
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_A, bMaskDWord, 0x2813001f);
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_B, bMaskDWord, 0x82110000);
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_B, bMaskDWord, 0x28110000);
+
+ /* LO calibration setting */
+ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Rsp, bMaskDWord, 0x0046a8d1);
+
+ /* enter IQK mode */
+ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x808000);
+
+ /* Ant switch */
+ if (configPathB || (RF_Path == 0))
+ /* wifi switch to S1 */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, 0x00000000);
+ else
+ /* wifi switch to S0 */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, 0x00000280);
+
+ /* GNT_BT = 0 */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00000800);
+
+ /* One shot, path A LOK & IQK */
+ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
+ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
+
+ /* delay x ms */
+ /* PlatformStallExecution(IQK_DELAY_TIME_8723B*1000); */
+ mdelay(IQK_DELAY_TIME_8723B);
+
+ /* restore Ant Path */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, Path_SEL_BB);
+ /* GNT_BT = 1 */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00001800);
+
+ /* leave IQK mode */
+ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+
+ /* Check failed */
+ regEAC = PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_After_IQK_A_2, bMaskDWord);
+ regEA4 = PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_Before_IQK_A_2, bMaskDWord);
+
+ /* PA/PAD controlled by 0x0 */
+ /* leave IQK mode */
+ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0x780);
+
+ /* Allen 20131125 */
+ tmp = (regEAC & 0x03FF0000)>>16;
+ if ((tmp & 0x200) > 0)
+ tmp = 0x400 - tmp;
+
+ if (
+ !(regEAC & BIT27) && /* if Tx is OK, check whether Rx is OK */
+ (((regEA4 & 0x03FF0000)>>16) != 0x132) &&
+ (((regEAC & 0x03FF0000)>>16) != 0x36) &&
+ (((regEA4 & 0x03FF0000)>>16) < 0x110) &&
+ (((regEA4 & 0x03FF0000)>>16) > 0xf0) &&
+ (tmp < 0xf)
+ )
+ result |= 0x02;
+
+ return result;
+}
+
+/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */
+static u8 phy_PathB_IQK_8723B(struct adapter *padapter)
+{
+ u32 regEAC, regE94, regE9C, tmp, Path_SEL_BB/*, regEC4, regECC, Path_SEL_BB*/;
+ u8 result = 0x00;
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
+
+ /* Save RF Path */
+ Path_SEL_BB = PHY_QueryBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord);
+
+ /* leave IQK mode */
+ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+
+ /* in TXIQK mode */
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_WE_LUT, 0x80000, 0x1); */
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x20000); */
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0003f); */
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xc7f87); */
+ /* enable path B PA in TXIQK mode */
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xed, 0x20, 0x1);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0x43, bRFRegOffsetMask, 0x30fc1);
+
+
+
+ /* 1 Tx IQK */
+ /* IQK setting */
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK, bMaskDWord, 0x01007c00);
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK, bMaskDWord, 0x01004800);
+ /* path-A IQK setting */
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
+
+/* PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_A, bMaskDWord, 0x82140114); */
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_A, bMaskDWord, 0x821303ea);
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_A, bMaskDWord, 0x28110000);
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_B, bMaskDWord, 0x82110000);
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_B, bMaskDWord, 0x28110000);
+
+ /* LO calibration setting */
+ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Rsp, bMaskDWord, 0x00462911);
+
+ /* enter IQK mode */
+ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x808000);
+
+ /* switch to path B */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, 0x00000280);
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xb0, bRFRegOffsetMask, 0xeffe0); */
+
+ /* GNT_BT = 0 */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00000800);
+
+ /* One shot, path B LOK & IQK */
+ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
+ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
+
+ /* delay x ms */
+ /* PlatformStallExecution(IQK_DELAY_TIME_88E*1000); */
+ mdelay(IQK_DELAY_TIME_8723B);
+
+ /* restore Ant Path */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, Path_SEL_BB);
+ /* GNT_BT = 1 */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00001800);
+
+ /* leave IQK mode */
+ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+
+ /* Check failed */
+ regEAC = PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_After_IQK_A_2, bMaskDWord);
+ regE94 = PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_Before_IQK_A, bMaskDWord);
+ regE9C = PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_After_IQK_A, bMaskDWord);
+
+ /* Allen 20131125 */
+ tmp = (regE9C & 0x03FF0000)>>16;
+ if ((tmp & 0x200) > 0)
+ tmp = 0x400 - tmp;
+
+ if (
+ !(regEAC & BIT28) &&
+ (((regE94 & 0x03FF0000)>>16) != 0x142) &&
+ (((regE9C & 0x03FF0000)>>16) != 0x42) &&
+ (((regE94 & 0x03FF0000)>>16) < 0x110) &&
+ (((regE94 & 0x03FF0000)>>16) > 0xf0) &&
+ (tmp < 0xf)
+ )
+ result |= 0x01;
+
+ return result;
+}
+
+/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */
+static u8 phy_PathB_RxIQK8723B(struct adapter *padapter, bool configPathB)
+{
+ u32 regE94, regE9C, regEA4, regEAC, u4tmp, tmp, Path_SEL_BB;
+ u8 result = 0x00;
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
+
+ /* Save RF Path */
+ Path_SEL_BB = PHY_QueryBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord);
+ /* leave IQK mode */
+ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+
+ /* switch to path B */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, 0x00000280);
+ /* modify RXIQK mode table */
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7fb7);
+ /* open PA S1 & SMIXER */
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xed, 0x20, 0x1);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0x43, bRFRegOffsetMask, 0x30fcd);
+
+
+ /* IQK setting */
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK, bMaskDWord, 0x01007c00);
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK, bMaskDWord, 0x01004800);
+
+
+ /* path-B IQK setting */
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
+
+/* PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_A, bMaskDWord, 0x82160c1f); */
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_A, bMaskDWord, 0x82130ff0);
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_A, bMaskDWord, 0x28110000);
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_B, bMaskDWord, 0x82110000);
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_B, bMaskDWord, 0x28110000);
+
+ /* LO calibration setting */
+ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
+
+ /* enter IQK mode */
+ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x808000);
+
+ /* switch to path B */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, 0x00000280);
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xb0, bRFRegOffsetMask, 0xeffe0); */
+
+ /* GNT_BT = 0 */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00000800);
+
+ /* One shot, path B TXIQK @ RXIQK */
+ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
+ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
+
+
+ /* delay x ms */
+ /* PlatformStallExecution(IQK_DELAY_TIME_88E*1000); */
+ mdelay(IQK_DELAY_TIME_8723B);
+
+ /* restore Ant Path */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, Path_SEL_BB);
+ /* GNT_BT = 1 */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00001800);
+
+ /* leave IQK mode */
+ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+
+ /* Check failed */
+ regEAC = PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_After_IQK_A_2, bMaskDWord);
+ regE94 = PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_Before_IQK_A, bMaskDWord);
+ regE9C = PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_After_IQK_A, bMaskDWord);
+
+ /* Allen 20131125 */
+ tmp = (regE9C & 0x03FF0000)>>16;
+ if ((tmp & 0x200) > 0)
+ tmp = 0x400 - tmp;
+
+ if (
+ !(regEAC & BIT28) &&
+ (((regE94 & 0x03FF0000)>>16) != 0x142) &&
+ (((regE9C & 0x03FF0000)>>16) != 0x42) &&
+ (((regE94 & 0x03FF0000)>>16) < 0x110) &&
+ (((regE94 & 0x03FF0000)>>16) > 0xf0) &&
+ (tmp < 0xf)
+ )
+ result |= 0x01;
+ else /* if Tx not OK, ignore Rx */
+ return result;
+
+ u4tmp = 0x80007C00 | (regE94&0x3FF0000) | ((regE9C&0x3FF0000) >> 16);
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK, bMaskDWord, u4tmp);
+
+ /* modify RXIQK mode table */
+ /* 20121009, Kordan> RF Mode = 3 */
+ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7d77);
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_WE_LUT, 0x80000, 0x0); */
+
+ /* open PA S1 & close SMIXER */
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xed, 0x20, 0x1);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0x43, bRFRegOffsetMask, 0x30ebd);
+
+ /* PA, PAD setting */
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0xf80); */
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0x56, bRFRegOffsetMask, 0x51000); */
+
+ /* IQK setting */
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK, bMaskDWord, 0x01004800);
+
+ /* path-B IQK setting */
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
+
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_A, bMaskDWord, 0x82110000);
+/* PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_A, bMaskDWord, 0x281604c2); */
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_A, bMaskDWord, 0x2813001f);
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_B, bMaskDWord, 0x82110000);
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_B, bMaskDWord, 0x28110000);
+
+ /* LO calibration setting */
+ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Rsp, bMaskDWord, 0x0046a8d1);
+
+ /* enter IQK mode */
+ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x808000);
+
+ /* switch to path B */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, 0x00000280);
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xb0, bRFRegOffsetMask, 0xeffe0); */
+
+ /* GNT_BT = 0 */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00000800);
+
+ /* One shot, path B LOK & IQK */
+ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
+ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
+
+ /* delay x ms */
+ /* PlatformStallExecution(IQK_DELAY_TIME_88E*1000); */
+ mdelay(IQK_DELAY_TIME_8723B);
+
+ /* restore Ant Path */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, Path_SEL_BB);
+ /* GNT_BT = 1 */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00001800);
+
+ /* leave IQK mode */
+ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+
+ /* Check failed */
+ regEAC = PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_After_IQK_A_2, bMaskDWord);
+ regEA4 = PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_Before_IQK_A_2, bMaskDWord);
+
+ /* PA/PAD controlled by 0x0 */
+ /* leave IQK mode */
+/* PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, 0xffffff00, 0x00000000); */
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_B, 0xdf, bRFRegOffsetMask, 0x180); */
+
+
+
+ /* Allen 20131125 */
+ tmp = (regEAC & 0x03FF0000)>>16;
+ if ((tmp & 0x200) > 0)
+ tmp = 0x400 - tmp;
+
+ if (
+ !(regEAC & BIT27) && /* if Tx is OK, check whether Rx is OK */
+ (((regEA4 & 0x03FF0000)>>16) != 0x132) &&
+ (((regEAC & 0x03FF0000)>>16) != 0x36) &&
+ (((regEA4 & 0x03FF0000)>>16) < 0x110) &&
+ (((regEA4 & 0x03FF0000)>>16) > 0xf0) &&
+ (tmp < 0xf)
+ )
+ result |= 0x02;
+
+ return result;
+}
+
+static void _PHY_PathAFillIQKMatrix8723B(
+ struct adapter *padapter,
+ bool bIQKOK,
+ s32 result[][8],
+ u8 final_candidate,
+ bool bTxOnly
+)
+{
+ u32 Oldval_0, X, TX0_A, reg;
+ s32 Y, TX0_C;
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
+
+ struct odm_rf_cal_t *pRFCalibrateInfo = &pDM_Odm->RFCalibrateInfo;
+
+ if (final_candidate == 0xFF)
+ return;
+
+ else if (bIQKOK) {
+ Oldval_0 = (PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XATxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
+
+ X = result[final_candidate][0];
+ if ((X & 0x00000200) != 0)
+ X = X | 0xFFFFFC00;
+ TX0_A = (X * Oldval_0) >> 8;
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XATxIQImbalance, 0x3FF, TX0_A);
+
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, BIT(31), ((X*Oldval_0>>7) & 0x1));
+
+ Y = result[final_candidate][1];
+ if ((Y & 0x00000200) != 0)
+ Y = Y | 0xFFFFFC00;
+
+ /* 2 Tx IQC */
+ TX0_C = (Y * Oldval_0) >> 8;
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XCTxAFE, 0xF0000000, ((TX0_C&0x3C0)>>6));
+ pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC94][KEY] = rOFDM0_XCTxAFE;
+ pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC94][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XCTxAFE, bMaskDWord);
+
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XATxIQImbalance, 0x003F0000, (TX0_C&0x3F));
+ pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC80][KEY] = rOFDM0_XATxIQImbalance;
+ pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC80][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XATxIQImbalance, bMaskDWord);
+
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, BIT(29), ((Y*Oldval_0>>7) & 0x1));
+ pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC4C][KEY] = rOFDM0_ECCAThreshold;
+ pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC4C][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskDWord);
+
+ if (bTxOnly) {
+ /* <20130226, Kordan> Saving RxIQC, otherwise not initialized. */
+ pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xCA0][KEY] = rOFDM0_RxIQExtAnta;
+ pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xCA0][VAL] = 0xfffffff & PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_RxIQExtAnta, bMaskDWord);
+ pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xC14][KEY] = rOFDM0_XARxIQImbalance;
+/* pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xC14][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XARxIQImbalance, bMaskDWord); */
+ pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xC14][VAL] = 0x40000100;
+ return;
+ }
+
+ reg = result[final_candidate][2];
+
+ /* 2 Rx IQC */
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XARxIQImbalance, 0x3FF, reg);
+ reg = result[final_candidate][3] & 0x3F;
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XARxIQImbalance, 0xFC00, reg);
+ pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xC14][KEY] = rOFDM0_XARxIQImbalance;
+ pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xC14][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XARxIQImbalance, bMaskDWord);
+
+ reg = (result[final_candidate][3] >> 6) & 0xF;
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_RxIQExtAnta, 0xF0000000, reg);
+ pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xCA0][KEY] = rOFDM0_RxIQExtAnta;
+ pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xCA0][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_RxIQExtAnta, bMaskDWord);
+
+ }
+}
+
+static void _PHY_PathBFillIQKMatrix8723B(
+ struct adapter *padapter,
+ bool bIQKOK,
+ s32 result[][8],
+ u8 final_candidate,
+ bool bTxOnly /* do Tx only */
+)
+{
+ u32 Oldval_1, X, TX1_A, reg;
+ s32 Y, TX1_C;
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
+
+ struct odm_rf_cal_t *pRFCalibrateInfo = &pDM_Odm->RFCalibrateInfo;
+
+ if (final_candidate == 0xFF)
+ return;
+
+ else if (bIQKOK) {
+ Oldval_1 = (PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XBTxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
+
+ X = result[final_candidate][4];
+ if ((X & 0x00000200) != 0)
+ X = X | 0xFFFFFC00;
+ TX1_A = (X * Oldval_1) >> 8;
+
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XBTxIQImbalance, 0x3FF, TX1_A);
+
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, BIT(27), ((X*Oldval_1>>7) & 0x1));
+
+ Y = result[final_candidate][5];
+ if ((Y & 0x00000200) != 0)
+ Y = Y | 0xFFFFFC00;
+
+ TX1_C = (Y * Oldval_1) >> 8;
+
+ /* 2 Tx IQC */
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XDTxAFE, 0xF0000000, ((TX1_C&0x3C0)>>6));
+/* pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC9C][KEY] = rOFDM0_XDTxAFE; */
+/* pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC9C][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XDTxAFE, bMaskDWord); */
+ pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC94][KEY] = rOFDM0_XCTxAFE;
+ pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC94][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XDTxAFE, bMaskDWord);
+
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XBTxIQImbalance, 0x003F0000, (TX1_C&0x3F));
+ pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC80][KEY] = rOFDM0_XATxIQImbalance;
+ pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC80][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XBTxIQImbalance, bMaskDWord);
+
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, BIT(25), ((Y*Oldval_1>>7) & 0x1));
+ pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC4C][KEY] = rOFDM0_ECCAThreshold;
+ pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC4C][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskDWord);
+
+ if (bTxOnly) {
+ pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xC14][KEY] = rOFDM0_XARxIQImbalance;
+/* pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xC14][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XARxIQImbalance, bMaskDWord); */
+ pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xC14][VAL] = 0x40000100;
+ pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xCA0][KEY] = rOFDM0_RxIQExtAnta;
+ pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xCA0][VAL] = 0x0fffffff & PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_RxIQExtAnta, bMaskDWord);
+ return;
+ }
+
+ /* 2 Rx IQC */
+ reg = result[final_candidate][6];
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XBRxIQImbalance, 0x3FF, reg);
+ reg = result[final_candidate][7] & 0x3F;
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XBRxIQImbalance, 0xFC00, reg);
+ pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xC14][KEY] = rOFDM0_XARxIQImbalance;
+ pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xC14][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XBRxIQImbalance, bMaskDWord);
+
+ reg = (result[final_candidate][7] >> 6) & 0xF;
+/* PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_AGCRSSITable, 0x0000F000, reg); */
+ pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xCA0][KEY] = rOFDM0_RxIQExtAnta;
+ pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xCA0][VAL] = (reg << 28)|(PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_RxIQExtAnta, bMaskDWord)&0x0fffffff);
+ }
+}
+
+/* */
+/* 2011/07/26 MH Add an API for testing IQK fail case. */
+/* */
+/* MP Already declare in odm.c */
+
+void ODM_SetIQCbyRFpath(struct dm_odm_t *pDM_Odm, u32 RFpath)
+{
+
+ struct odm_rf_cal_t *pRFCalibrateInfo = &pDM_Odm->RFCalibrateInfo;
+
+ if (
+ (pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC80][VAL] != 0x0) &&
+ (pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xC14][VAL] != 0x0) &&
+ (pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC80][VAL] != 0x0) &&
+ (pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xC14][VAL] != 0x0)
+ ) {
+ if (RFpath) { /* S1: RFpath = 0, S0:RFpath = 1 */
+ /* S0 TX IQC */
+ PHY_SetBBReg(pDM_Odm->Adapter, pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC94][KEY], bMaskDWord, pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC94][VAL]);
+ PHY_SetBBReg(pDM_Odm->Adapter, pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC80][KEY], bMaskDWord, pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC80][VAL]);
+ PHY_SetBBReg(pDM_Odm->Adapter, pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC4C][KEY], bMaskDWord, pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC4C][VAL]);
+ /* S0 RX IQC */
+ PHY_SetBBReg(pDM_Odm->Adapter, pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xC14][KEY], bMaskDWord, pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xC14][VAL]);
+ PHY_SetBBReg(pDM_Odm->Adapter, pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xCA0][KEY], bMaskDWord, pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xCA0][VAL]);
+ } else {
+ /* S1 TX IQC */
+ PHY_SetBBReg(pDM_Odm->Adapter, pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC94][KEY], bMaskDWord, pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC94][VAL]);
+ PHY_SetBBReg(pDM_Odm->Adapter, pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC80][KEY], bMaskDWord, pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC80][VAL]);
+ PHY_SetBBReg(pDM_Odm->Adapter, pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC4C][KEY], bMaskDWord, pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC4C][VAL]);
+ /* S1 RX IQC */
+ PHY_SetBBReg(pDM_Odm->Adapter, pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xC14][KEY], bMaskDWord, pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xC14][VAL]);
+ PHY_SetBBReg(pDM_Odm->Adapter, pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xCA0][KEY], bMaskDWord, pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xCA0][VAL]);
+ }
+ }
+}
+
+static bool ODM_CheckPowerStatus(struct adapter *Adapter)
+{
+ return true;
+}
+
+static void _PHY_SaveADDARegisters8723B(
+ struct adapter *padapter,
+ u32 *ADDAReg,
+ u32 *ADDABackup,
+ u32 RegisterNum
+)
+{
+ u32 i;
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
+
+ if (!ODM_CheckPowerStatus(padapter))
+ return;
+
+ for (i = 0 ; i < RegisterNum ; i++) {
+ ADDABackup[i] = PHY_QueryBBReg(pDM_Odm->Adapter, ADDAReg[i], bMaskDWord);
+ }
+}
+
+
+static void _PHY_SaveMACRegisters8723B(
+ struct adapter *padapter, u32 *MACReg, u32 *MACBackup
+)
+{
+ u32 i;
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
+
+ for (i = 0 ; i < (IQK_MAC_REG_NUM - 1); i++) {
+ MACBackup[i] = rtw_read8(pDM_Odm->Adapter, MACReg[i]);
+ }
+ MACBackup[i] = rtw_read32(pDM_Odm->Adapter, MACReg[i]);
+
+}
+
+
+static void _PHY_ReloadADDARegisters8723B(
+ struct adapter *padapter,
+ u32 *ADDAReg,
+ u32 *ADDABackup,
+ u32 RegiesterNum
+)
+{
+ u32 i;
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
+
+ for (i = 0 ; i < RegiesterNum; i++) {
+ PHY_SetBBReg(pDM_Odm->Adapter, ADDAReg[i], bMaskDWord, ADDABackup[i]);
+ }
+}
+
+static void _PHY_ReloadMACRegisters8723B(
+ struct adapter *padapter, u32 *MACReg, u32 *MACBackup
+)
+{
+ u32 i;
+
+ for (i = 0 ; i < (IQK_MAC_REG_NUM - 1); i++) {
+ rtw_write8(padapter, MACReg[i], (u8)MACBackup[i]);
+ }
+ rtw_write32(padapter, MACReg[i], MACBackup[i]);
+}
+
+
+static void _PHY_PathADDAOn8723B(
+ struct adapter *padapter,
+ u32 *ADDAReg,
+ bool is2T
+)
+{
+ u32 pathOn;
+ u32 i;
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
+
+ pathOn = 0x01c00014;
+ if (!is2T) {
+ pathOn = 0x01c00014;
+ PHY_SetBBReg(pDM_Odm->Adapter, ADDAReg[0], bMaskDWord, 0x01c00014);
+ } else {
+ PHY_SetBBReg(pDM_Odm->Adapter, ADDAReg[0], bMaskDWord, pathOn);
+ }
+
+ for (i = 1 ; i < IQK_ADDA_REG_NUM ; i++) {
+ PHY_SetBBReg(pDM_Odm->Adapter, ADDAReg[i], bMaskDWord, pathOn);
+ }
+
+}
+
+static void _PHY_MACSettingCalibration8723B(
+ struct adapter *padapter, u32 *MACReg, u32 *MACBackup
+)
+{
+ u32 i = 0;
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
+
+ rtw_write8(pDM_Odm->Adapter, MACReg[i], 0x3F);
+
+ for (i = 1 ; i < (IQK_MAC_REG_NUM - 1); i++) {
+ rtw_write8(pDM_Odm->Adapter, MACReg[i], (u8)(MACBackup[i]&(~BIT3)));
+ }
+ rtw_write8(pDM_Odm->Adapter, MACReg[i], (u8)(MACBackup[i]&(~BIT5)));
+
+}
+
+static bool phy_SimularityCompare_8723B(
+ struct adapter *padapter,
+ s32 result[][8],
+ u8 c1,
+ u8 c2
+)
+{
+ u32 i, j, diff, SimularityBitMap, bound = 0;
+ u8 final_candidate[2] = {0xFF, 0xFF}; /* for path A and path B */
+ bool bResult = true;
+ s32 tmp1 = 0, tmp2 = 0;
+
+ bound = 8;
+ SimularityBitMap = 0;
+
+ for (i = 0; i < bound; i++) {
+
+ if ((i == 1) || (i == 3) || (i == 5) || (i == 7)) {
+ if ((result[c1][i] & 0x00000200) != 0)
+ tmp1 = result[c1][i] | 0xFFFFFC00;
+ else
+ tmp1 = result[c1][i];
+
+ if ((result[c2][i] & 0x00000200) != 0)
+ tmp2 = result[c2][i] | 0xFFFFFC00;
+ else
+ tmp2 = result[c2][i];
+ } else {
+ tmp1 = result[c1][i];
+ tmp2 = result[c2][i];
+ }
+
+ diff = (tmp1 > tmp2) ? (tmp1 - tmp2) : (tmp2 - tmp1);
+
+ if (diff > MAX_TOLERANCE) {
+ if ((i == 2 || i == 6) && !SimularityBitMap) {
+ if (result[c1][i]+result[c1][i+1] == 0)
+ final_candidate[(i/4)] = c2;
+ else if (result[c2][i]+result[c2][i+1] == 0)
+ final_candidate[(i/4)] = c1;
+ else
+ SimularityBitMap = SimularityBitMap|(1<<i);
+ } else
+ SimularityBitMap = SimularityBitMap|(1<<i);
+ }
+ }
+
+ if (SimularityBitMap == 0) {
+ for (i = 0; i < (bound/4); i++) {
+ if (final_candidate[i] != 0xFF) {
+ for (j = i*4; j < (i+1)*4-2; j++)
+ result[3][j] = result[final_candidate[i]][j];
+ bResult = false;
+ }
+ }
+ return bResult;
+ } else {
+
+ if (!(SimularityBitMap & 0x03)) { /* path A TX OK */
+ for (i = 0; i < 2; i++)
+ result[3][i] = result[c1][i];
+ }
+
+ if (!(SimularityBitMap & 0x0c)) { /* path A RX OK */
+ for (i = 2; i < 4; i++)
+ result[3][i] = result[c1][i];
+ }
+
+ if (!(SimularityBitMap & 0x30)) { /* path B TX OK */
+ for (i = 4; i < 6; i++)
+ result[3][i] = result[c1][i];
+ }
+
+ if (!(SimularityBitMap & 0xc0)) { /* path B RX OK */
+ for (i = 6; i < 8; i++)
+ result[3][i] = result[c1][i];
+ }
+ return false;
+ }
+}
+
+
+
+static void phy_IQCalibrate_8723B(
+ struct adapter *padapter,
+ s32 result[][8],
+ u8 t,
+ bool is2T,
+ u8 RF_Path
+)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
+
+ u32 i;
+ u8 PathAOK, PathBOK;
+ u8 tmp0xc50 = (u8)PHY_QueryBBReg(pDM_Odm->Adapter, 0xC50, bMaskByte0);
+ u8 tmp0xc58 = (u8)PHY_QueryBBReg(pDM_Odm->Adapter, 0xC58, bMaskByte0);
+ u32 ADDA_REG[IQK_ADDA_REG_NUM] = {
+ rFPGA0_XCD_SwitchControl,
+ rBlue_Tooth,
+ rRx_Wait_CCA,
+ rTx_CCK_RFON,
+ rTx_CCK_BBON,
+ rTx_OFDM_RFON,
+ rTx_OFDM_BBON,
+ rTx_To_Rx,
+ rTx_To_Tx,
+ rRx_CCK,
+ rRx_OFDM,
+ rRx_Wait_RIFS,
+ rRx_TO_Rx,
+ rStandby,
+ rSleep,
+ rPMPD_ANAEN
+ };
+ u32 IQK_MAC_REG[IQK_MAC_REG_NUM] = {
+ REG_TXPAUSE,
+ REG_BCN_CTRL,
+ REG_BCN_CTRL_1,
+ REG_GPIO_MUXCFG
+ };
+
+ /* since 92C & 92D have the different define in IQK_BB_REG */
+ u32 IQK_BB_REG_92C[IQK_BB_REG_NUM] = {
+ rOFDM0_TRxPathEnable,
+ rOFDM0_TRMuxPar,
+ rFPGA0_XCD_RFInterfaceSW,
+ rConfig_AntA,
+ rConfig_AntB,
+ rFPGA0_XAB_RFInterfaceSW,
+ rFPGA0_XA_RFInterfaceOE,
+ rFPGA0_XB_RFInterfaceOE,
+ rCCK0_AFESetting
+ };
+ const u32 retryCount = 2;
+
+ /* Note: IQ calibration must be performed after loading */
+ /* PHY_REG.txt , and radio_a, radio_b.txt */
+
+ /* u32 bbvalue; */
+
+ if (t == 0) {
+
+ /* Save ADDA parameters, turn Path A ADDA on */
+ _PHY_SaveADDARegisters8723B(padapter, ADDA_REG, pDM_Odm->RFCalibrateInfo.ADDA_backup, IQK_ADDA_REG_NUM);
+ _PHY_SaveMACRegisters8723B(padapter, IQK_MAC_REG, pDM_Odm->RFCalibrateInfo.IQK_MAC_backup);
+ _PHY_SaveADDARegisters8723B(padapter, IQK_BB_REG_92C, pDM_Odm->RFCalibrateInfo.IQK_BB_backup, IQK_BB_REG_NUM);
+ }
+
+ _PHY_PathADDAOn8723B(padapter, ADDA_REG, is2T);
+
+/* no serial mode */
+
+ /* save RF path for 8723B */
+/* Path_SEL_BB = PHY_QueryBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord); */
+/* Path_SEL_RF = PHY_QueryRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xb0, 0xfffff); */
+
+ /* MAC settings */
+ _PHY_MACSettingCalibration8723B(padapter, IQK_MAC_REG, pDM_Odm->RFCalibrateInfo.IQK_MAC_backup);
+
+ /* BB setting */
+ /* PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_RFMOD, BIT24, 0x00); */
+ PHY_SetBBReg(pDM_Odm->Adapter, rCCK0_AFESetting, 0x0f000000, 0xf);
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_TRxPathEnable, bMaskDWord, 0x03a05600);
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_TRMuxPar, bMaskDWord, 0x000800e4);
+ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22204000);
+
+
+/* PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_XAB_RFInterfaceSW, BIT10, 0x01); */
+/* PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_XAB_RFInterfaceSW, BIT26, 0x01); */
+/* PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_XA_RFInterfaceOE, BIT10, 0x00); */
+/* PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_XB_RFInterfaceOE, BIT10, 0x00); */
+
+
+/* RX IQ calibration setting for 8723B D cut large current issue when leaving IPS */
+
+ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7fb7);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xed, 0x20, 0x1);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0x43, bRFRegOffsetMask, 0x60fbd);
+
+/* path A TX IQK */
+ for (i = 0 ; i < retryCount ; i++) {
+ PathAOK = phy_PathA_IQK_8723B(padapter, is2T, RF_Path);
+/* if (PathAOK == 0x03) { */
+ if (PathAOK == 0x01) {
+ /* Path A Tx IQK Success */
+ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+ pDM_Odm->RFCalibrateInfo.TxLOK[RF_PATH_A] = PHY_QueryRFReg(pDM_Odm->Adapter, RF_PATH_A, 0x8, bRFRegOffsetMask);
+
+ result[t][0] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16;
+ result[t][1] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16;
+ break;
+ }
+ }
+
+/* path A RXIQK */
+ for (i = 0 ; i < retryCount ; i++) {
+ PathAOK = phy_PathA_RxIQK8723B(padapter, is2T, RF_Path);
+ if (PathAOK == 0x03) {
+/* result[t][0] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16; */
+/* result[t][1] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16; */
+ result[t][2] = (PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_Before_IQK_A_2, bMaskDWord)&0x3FF0000)>>16;
+ result[t][3] = (PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_After_IQK_A_2, bMaskDWord)&0x3FF0000)>>16;
+ break;
+ }
+ }
+
+ if (0x00 == PathAOK) {
+ }
+
+/* path B IQK */
+ if (is2T) {
+
+ /* path B TX IQK */
+ for (i = 0 ; i < retryCount ; i++) {
+ PathBOK = phy_PathB_IQK_8723B(padapter);
+ if (PathBOK == 0x01) {
+ /* Path B Tx IQK Success */
+ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+ pDM_Odm->RFCalibrateInfo.TxLOK[RF_PATH_B] = PHY_QueryRFReg(pDM_Odm->Adapter, RF_PATH_B, 0x8, bRFRegOffsetMask);
+
+ result[t][4] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16;
+ result[t][5] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16;
+ break;
+ }
+ }
+
+/* path B RX IQK */
+ for (i = 0 ; i < retryCount ; i++) {
+ PathBOK = phy_PathB_RxIQK8723B(padapter, is2T);
+ if (PathBOK == 0x03) {
+/* result[t][0] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16; */
+/* result[t][1] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16; */
+ result[t][6] = (PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_Before_IQK_A_2, bMaskDWord)&0x3FF0000)>>16;
+ result[t][7] = (PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_After_IQK_A_2, bMaskDWord)&0x3FF0000)>>16;
+ break;
+ }
+ }
+
+/* Allen end */
+ }
+
+ /* Back to BB mode, load original value */
+ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0);
+
+ if (t != 0) {
+ /* Reload ADDA power saving parameters */
+ _PHY_ReloadADDARegisters8723B(padapter, ADDA_REG, pDM_Odm->RFCalibrateInfo.ADDA_backup, IQK_ADDA_REG_NUM);
+
+ /* Reload MAC parameters */
+ _PHY_ReloadMACRegisters8723B(padapter, IQK_MAC_REG, pDM_Odm->RFCalibrateInfo.IQK_MAC_backup);
+
+ _PHY_ReloadADDARegisters8723B(padapter, IQK_BB_REG_92C, pDM_Odm->RFCalibrateInfo.IQK_BB_backup, IQK_BB_REG_NUM);
+
+ /* Reload RF path */
+/* PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, Path_SEL_BB); */
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xb0, 0xfffff, Path_SEL_RF); */
+
+ /* Allen initial gain 0xc50 */
+ /* Restore RX initial gain */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0xc50, bMaskByte0, 0x50);
+ PHY_SetBBReg(pDM_Odm->Adapter, 0xc50, bMaskByte0, tmp0xc50);
+ if (is2T) {
+ PHY_SetBBReg(pDM_Odm->Adapter, 0xc58, bMaskByte0, 0x50);
+ PHY_SetBBReg(pDM_Odm->Adapter, 0xc58, bMaskByte0, tmp0xc58);
+ }
+
+ /* load 0xe30 IQC default value */
+ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_A, bMaskDWord, 0x01008c00);
+ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_A, bMaskDWord, 0x01008c00);
+
+ }
+
+}
+
+
+static void phy_LCCalibrate_8723B(struct dm_odm_t *pDM_Odm, bool is2T)
+{
+ u8 tmpReg;
+ u32 RF_Amode = 0, RF_Bmode = 0, LC_Cal;
+ struct adapter *padapter = pDM_Odm->Adapter;
+
+ /* Check continuous TX and Packet TX */
+ tmpReg = rtw_read8(pDM_Odm->Adapter, 0xd03);
+
+ if ((tmpReg&0x70) != 0) /* Deal with contisuous TX case */
+ rtw_write8(pDM_Odm->Adapter, 0xd03, tmpReg&0x8F); /* disable all continuous TX */
+ else /* Deal with Packet TX case */
+ rtw_write8(pDM_Odm->Adapter, REG_TXPAUSE, 0xFF); /* block all queues */
+
+ if ((tmpReg&0x70) != 0) {
+ /* 1. Read original RF mode */
+ /* Path-A */
+ RF_Amode = PHY_QueryRFReg(padapter, RF_PATH_A, RF_AC, bMask12Bits);
+
+ /* Path-B */
+ if (is2T)
+ RF_Bmode = PHY_QueryRFReg(padapter, RF_PATH_B, RF_AC, bMask12Bits);
+
+ /* 2. Set RF mode = standby mode */
+ /* Path-A */
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_AC, bMask12Bits, (RF_Amode&0x8FFFF)|0x10000);
+
+ /* Path-B */
+ if (is2T)
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_B, RF_AC, bMask12Bits, (RF_Bmode&0x8FFFF)|0x10000);
+ }
+
+ /* 3. Read RF reg18 */
+ LC_Cal = PHY_QueryRFReg(padapter, RF_PATH_A, RF_CHNLBW, bMask12Bits);
+
+ /* 4. Set LC calibration begin bit15 */
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xB0, bRFRegOffsetMask, 0xDFBE0); /* LDO ON */
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_CHNLBW, bMask12Bits, LC_Cal|0x08000);
+
+ mdelay(100);
+
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xB0, bRFRegOffsetMask, 0xDFFE0); /* LDO OFF */
+
+ /* Channel 10 LC calibration issue for 8723bs with 26M xtal */
+ if (pDM_Odm->SupportInterface == ODM_ITRF_SDIO && pDM_Odm->PackageType >= 0x2) {
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_CHNLBW, bMask12Bits, LC_Cal);
+ }
+
+ /* Restore original situation */
+ if ((tmpReg&0x70) != 0) { /* Deal with contisuous TX case */
+ /* Path-A */
+ rtw_write8(pDM_Odm->Adapter, 0xd03, tmpReg);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_AC, bMask12Bits, RF_Amode);
+
+ /* Path-B */
+ if (is2T)
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_B, RF_AC, bMask12Bits, RF_Bmode);
+ } else /* Deal with Packet TX case */
+ rtw_write8(pDM_Odm->Adapter, REG_TXPAUSE, 0x00);
+}
+
+/* IQK version:V2.5 20140123 */
+/* IQK is controlled by Is2ant, RF path */
+void PHY_IQCalibrate_8723B(
+ struct adapter *padapter,
+ bool bReCovery,
+ bool bRestore,
+ bool Is2ant, /* false:1ant, true:2-ant */
+ u8 RF_Path /* 0:S1, 1:S0 */
+)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+
+ struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
+
+ s32 result[4][8]; /* last is final result */
+ u8 i, final_candidate;
+ bool bPathAOK, bPathBOK;
+ s32 RegE94, RegE9C, RegEA4, RegEB4, RegEBC, RegEC4, RegTmp = 0;
+ bool is12simular, is13simular, is23simular;
+ bool bSingleTone = false, bCarrierSuppression = false;
+ u32 IQK_BB_REG_92C[IQK_BB_REG_NUM] = {
+ rOFDM0_XARxIQImbalance,
+ rOFDM0_XBRxIQImbalance,
+ rOFDM0_ECCAThreshold,
+ rOFDM0_AGCRSSITable,
+ rOFDM0_XATxIQImbalance,
+ rOFDM0_XBTxIQImbalance,
+ rOFDM0_XCTxAFE,
+ rOFDM0_XDTxAFE,
+ rOFDM0_RxIQExtAnta
+ };
+/* u32 Path_SEL_BB = 0; */
+ u32 GNT_BT_default;
+
+ if (!ODM_CheckPowerStatus(padapter))
+ return;
+
+ if (!(pDM_Odm->SupportAbility & ODM_RF_CALIBRATION))
+ return;
+
+ /* 20120213<Kordan> Turn on when continuous Tx to pass lab testing. (required by Edlu) */
+ if (bSingleTone || bCarrierSuppression)
+ return;
+
+ if (pDM_Odm->RFCalibrateInfo.bIQKInProgress)
+ return;
+
+
+ pDM_Odm->RFCalibrateInfo.bIQKInProgress = true;
+
+ if (bRestore) {
+ u32 offset, data;
+ u8 path, bResult = SUCCESS;
+ struct odm_rf_cal_t *pRFCalibrateInfo = &pDM_Odm->RFCalibrateInfo;
+
+ path = (PHY_QueryBBReg(pDM_Odm->Adapter, rS0S1_PathSwitch, bMaskByte0) == 0x00) ? RF_PATH_A : RF_PATH_B;
+
+ /* Restore TX IQK */
+ for (i = 0; i < 3; ++i) {
+ offset = pRFCalibrateInfo->TxIQC_8723B[path][i][0];
+ data = pRFCalibrateInfo->TxIQC_8723B[path][i][1];
+ if ((offset == 0) || (data == 0)) {
+ bResult = FAIL;
+ break;
+ }
+ PHY_SetBBReg(pDM_Odm->Adapter, offset, bMaskDWord, data);
+ }
+
+ /* Restore RX IQK */
+ for (i = 0; i < 2; ++i) {
+ offset = pRFCalibrateInfo->RxIQC_8723B[path][i][0];
+ data = pRFCalibrateInfo->RxIQC_8723B[path][i][1];
+ if ((offset == 0) || (data == 0)) {
+ bResult = FAIL;
+ break;
+ }
+ PHY_SetBBReg(pDM_Odm->Adapter, offset, bMaskDWord, data);
+ }
+
+ if (pDM_Odm->RFCalibrateInfo.TxLOK[RF_PATH_A] == 0) {
+ bResult = FAIL;
+ } else {
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXM_IDAC, bRFRegOffsetMask, pDM_Odm->RFCalibrateInfo.TxLOK[RF_PATH_A]);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_B, RF_TXM_IDAC, bRFRegOffsetMask, pDM_Odm->RFCalibrateInfo.TxLOK[RF_PATH_B]);
+ }
+
+ if (bResult == SUCCESS)
+ return;
+ }
+
+ if (bReCovery) {
+ _PHY_ReloadADDARegisters8723B(padapter, IQK_BB_REG_92C, pDM_Odm->RFCalibrateInfo.IQK_BB_backup_recover, 9);
+ return;
+ }
+
+ /* save default GNT_BT */
+ GNT_BT_default = PHY_QueryBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord);
+ /* Save RF Path */
+/* Path_SEL_BB = PHY_QueryBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord); */
+/* Path_SEL_RF = PHY_QueryRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xb0, 0xfffff); */
+
+ /* set GNT_BT = 0, pause BT traffic */
+/* PHY_SetBBReg(pDM_Odm->Adapter, 0x764, BIT12, 0x0); */
+/* PHY_SetBBReg(pDM_Odm->Adapter, 0x764, BIT11, 0x1); */
+
+
+ for (i = 0; i < 8; i++) {
+ result[0][i] = 0;
+ result[1][i] = 0;
+ result[2][i] = 0;
+ result[3][i] = 0;
+ }
+
+ final_candidate = 0xff;
+ bPathAOK = false;
+ bPathBOK = false;
+ is12simular = false;
+ is23simular = false;
+ is13simular = false;
+
+
+ for (i = 0; i < 3; i++) {
+ phy_IQCalibrate_8723B(padapter, result, i, Is2ant, RF_Path);
+
+ if (i == 1) {
+ is12simular = phy_SimularityCompare_8723B(padapter, result, 0, 1);
+ if (is12simular) {
+ final_candidate = 0;
+ break;
+ }
+ }
+
+ if (i == 2) {
+ is13simular = phy_SimularityCompare_8723B(padapter, result, 0, 2);
+ if (is13simular) {
+ final_candidate = 0;
+
+ break;
+ }
+
+ is23simular = phy_SimularityCompare_8723B(padapter, result, 1, 2);
+ if (is23simular) {
+ final_candidate = 1;
+ } else {
+ for (i = 0; i < 8; i++)
+ RegTmp += result[3][i];
+
+ if (RegTmp != 0)
+ final_candidate = 3;
+ else
+ final_candidate = 0xFF;
+ }
+ }
+ }
+
+ for (i = 0; i < 4; i++) {
+ RegE94 = result[i][0];
+ RegE9C = result[i][1];
+ RegEA4 = result[i][2];
+ RegEB4 = result[i][4];
+ RegEBC = result[i][5];
+ RegEC4 = result[i][6];
+ }
+
+ if (final_candidate != 0xff) {
+ pDM_Odm->RFCalibrateInfo.RegE94 = RegE94 = result[final_candidate][0];
+ pDM_Odm->RFCalibrateInfo.RegE9C = RegE9C = result[final_candidate][1];
+ RegEA4 = result[final_candidate][2];
+ pDM_Odm->RFCalibrateInfo.RegEB4 = RegEB4 = result[final_candidate][4];
+ pDM_Odm->RFCalibrateInfo.RegEBC = RegEBC = result[final_candidate][5];
+ RegEC4 = result[final_candidate][6];
+ bPathAOK = bPathBOK = true;
+ } else {
+ pDM_Odm->RFCalibrateInfo.RegE94 = pDM_Odm->RFCalibrateInfo.RegEB4 = 0x100; /* X default value */
+ pDM_Odm->RFCalibrateInfo.RegE9C = pDM_Odm->RFCalibrateInfo.RegEBC = 0x0; /* Y default value */
+ }
+
+ {
+ if (RegE94 != 0)
+ _PHY_PathAFillIQKMatrix8723B(padapter, bPathAOK, result, final_candidate, (RegEA4 == 0));
+ }
+ {
+ if (RegEB4 != 0)
+ _PHY_PathBFillIQKMatrix8723B(padapter, bPathBOK, result, final_candidate, (RegEC4 == 0));
+ }
+
+/* To Fix BSOD when final_candidate is 0xff */
+/* by sherry 20120321 */
+ if (final_candidate < 4) {
+ for (i = 0; i < IQK_Matrix_REG_NUM; i++)
+ pDM_Odm->RFCalibrateInfo.IQKMatrixRegSetting[0].Value[0][i] = result[final_candidate][i];
+ pDM_Odm->RFCalibrateInfo.IQKMatrixRegSetting[0].bIQKDone = true;
+ }
+
+ _PHY_SaveADDARegisters8723B(padapter, IQK_BB_REG_92C, pDM_Odm->RFCalibrateInfo.IQK_BB_backup_recover, 9);
+
+ /* restore GNT_BT */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, GNT_BT_default);
+ /* Restore RF Path */
+/* PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, Path_SEL_BB); */
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xb0, 0xfffff, Path_SEL_RF); */
+
+ /* Resotr RX mode table parameter */
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xe6177);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xed, 0x20, 0x1);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0x43, bRFRegOffsetMask, 0x300bd);
+
+ /* set GNT_BT = HW control */
+/* PHY_SetBBReg(pDM_Odm->Adapter, 0x764, BIT12, 0x0); */
+/* PHY_SetBBReg(pDM_Odm->Adapter, 0x764, BIT11, 0x0); */
+
+ if (Is2ant) {
+ if (RF_Path == 0x0) /* S1 */
+ ODM_SetIQCbyRFpath(pDM_Odm, 0);
+ else /* S0 */
+ ODM_SetIQCbyRFpath(pDM_Odm, 1);
+ }
+
+ pDM_Odm->RFCalibrateInfo.bIQKInProgress = false;
+}
+
+
+void PHY_LCCalibrate_8723B(struct dm_odm_t *pDM_Odm)
+{
+ bool bSingleTone = false, bCarrierSuppression = false;
+ u32 timeout = 2000, timecount = 0;
+
+ if (!(pDM_Odm->SupportAbility & ODM_RF_CALIBRATION))
+ return;
+
+ /* 20120213<Kordan> Turn on when continuous Tx to pass lab testing. (required by Edlu) */
+ if (bSingleTone || bCarrierSuppression)
+ return;
+
+ while (*(pDM_Odm->pbScanInProcess) && timecount < timeout) {
+ mdelay(50);
+ timecount += 50;
+ }
+
+ pDM_Odm->RFCalibrateInfo.bLCKInProgress = true;
+
+
+ phy_LCCalibrate_8723B(pDM_Odm, false);
+
+
+ pDM_Odm->RFCalibrateInfo.bLCKInProgress = false;
+}
diff --git a/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.h b/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.h
new file mode 100644
index 000000000..775095ad0
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#ifndef __HAL_PHY_RF_8723B_H__
+#define __HAL_PHY_RF_8723B_H__
+
+/*--------------------------Define Parameters-------------------------------*/
+#define IQK_DELAY_TIME_8723B 20 /* ms */
+#define IQK_DEFERRED_TIME_8723B 4
+#define index_mapping_NUM_8723B 15
+#define AVG_THERMAL_NUM_8723B 4
+#define RF_T_METER_8723B 0x42 /* */
+
+
+void ConfigureTxpowerTrack_8723B(struct txpwrtrack_cfg *pConfig);
+
+void DoIQK_8723B(
+ struct dm_odm_t *pDM_Odm,
+ u8 DeltaThermalIndex,
+ u8 ThermalValue,
+ u8 Threshold
+);
+
+void ODM_TxPwrTrackSetPwr_8723B(
+ struct dm_odm_t *pDM_Odm,
+ enum pwrtrack_method Method,
+ u8 RFPath,
+ u8 ChannelMappedIndex
+);
+
+/* 1 7. IQK */
+void PHY_IQCalibrate_8723B(
+ struct adapter *Adapter,
+ bool bReCovery,
+ bool bRestore,
+ bool Is2ant,
+ u8 RF_Path
+);
+
+void ODM_SetIQCbyRFpath(struct dm_odm_t *pDM_Odm, u32 RFpath);
+
+/* */
+/* LC calibrate */
+/* */
+void PHY_LCCalibrate_8723B(struct dm_odm_t *pDM_Odm);
+
+/* */
+/* AP calibrate */
+/* */
+void PHY_DigitalPredistortion_8723B(struct adapter *padapter);
+
+
+void _PHY_SaveADDARegisters_8723B(
+ struct adapter *padapter,
+ u32 *ADDAReg,
+ u32 *ADDABackup,
+ u32 RegisterNum
+);
+
+void _PHY_PathADDAOn_8723B(
+ struct adapter *padapter,
+ u32 *ADDAReg,
+ bool isPathAOn,
+ bool is2T
+);
+
+void _PHY_MACSettingCalibration_8723B(
+ struct adapter *padapter, u32 *MACReg, u32 *MACBackup
+);
+
+#endif /* #ifndef __HAL_PHY_RF_8188E_H__ */
diff --git a/drivers/staging/rtl8723bs/hal/HalPwrSeqCmd.c b/drivers/staging/rtl8723bs/hal/HalPwrSeqCmd.c
new file mode 100644
index 000000000..5f9e94a7e
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/HalPwrSeqCmd.c
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+/*++
+Copyright (c) Realtek Semiconductor Corp. All rights reserved.
+
+Module Name:
+ HalPwrSeqCmd.c
+
+Abstract:
+ Implement HW Power sequence configuration CMD handling routine for Realtek devices.
+
+Major Change History:
+ When Who What
+ ---------- --------------- -------------------------------
+ 2011-10-26 Lucas Modify to be compatible with SD4-CE driver.
+ 2011-07-07 Roger Create.
+
+--*/
+#include <drv_types.h>
+#include <rtw_debug.h>
+#include <HalPwrSeqCmd.h>
+
+
+/* */
+/* Description: */
+/* This routine deal with the Power Configuration CMDs parsing for RTL8723/RTL8188E Series IC. */
+/* */
+/* Assumption: */
+/* We should follow specific format which was released from HW SD. */
+/* */
+/* 2011.07.07, added by Roger. */
+/* */
+u8 HalPwrSeqCmdParsing(
+ struct adapter *padapter,
+ u8 CutVersion,
+ u8 FabVersion,
+ u8 InterfaceType,
+ struct wlan_pwr_cfg PwrSeqCmd[]
+)
+{
+ struct wlan_pwr_cfg PwrCfgCmd;
+ u8 bPollingBit = false;
+ u32 AryIdx = 0;
+ u8 value = 0;
+ u32 offset = 0;
+ u32 pollingCount = 0; /* polling autoload done. */
+ u32 maxPollingCnt = 5000;
+
+ do {
+ PwrCfgCmd = PwrSeqCmd[AryIdx];
+
+ /* 2 Only Handle the command whose FAB, CUT, and Interface are matched */
+ if (
+ (GET_PWR_CFG_FAB_MASK(PwrCfgCmd) & FabVersion) &&
+ (GET_PWR_CFG_CUT_MASK(PwrCfgCmd) & CutVersion) &&
+ (GET_PWR_CFG_INTF_MASK(PwrCfgCmd) & InterfaceType)
+ ) {
+ switch (GET_PWR_CFG_CMD(PwrCfgCmd)) {
+ case PWR_CMD_READ:
+ break;
+
+ case PWR_CMD_WRITE:
+ offset = GET_PWR_CFG_OFFSET(PwrCfgCmd);
+
+ /* */
+ /* <Roger_Notes> We should deal with interface specific address mapping for some interfaces, e.g., SDIO interface */
+ /* 2011.07.07. */
+ /* */
+ if (GET_PWR_CFG_BASE(PwrCfgCmd) == PWR_BASEADDR_SDIO) {
+ /* Read Back SDIO Local value */
+ value = SdioLocalCmd52Read1Byte(padapter, offset);
+
+ value &= ~(GET_PWR_CFG_MASK(PwrCfgCmd));
+ value |= (
+ GET_PWR_CFG_VALUE(PwrCfgCmd) &
+ GET_PWR_CFG_MASK(PwrCfgCmd)
+ );
+
+ /* Write Back SDIO Local value */
+ SdioLocalCmd52Write1Byte(padapter, offset, value);
+ } else {
+ /* Read the value from system register */
+ value = rtw_read8(padapter, offset);
+
+ value &= (~(GET_PWR_CFG_MASK(PwrCfgCmd)));
+ value |= (
+ GET_PWR_CFG_VALUE(PwrCfgCmd)
+ &GET_PWR_CFG_MASK(PwrCfgCmd)
+ );
+
+ /* Write the value back to system register */
+ rtw_write8(padapter, offset, value);
+ }
+ break;
+
+ case PWR_CMD_POLLING:
+
+ bPollingBit = false;
+ offset = GET_PWR_CFG_OFFSET(PwrCfgCmd);
+ do {
+ if (GET_PWR_CFG_BASE(PwrCfgCmd) == PWR_BASEADDR_SDIO)
+ value = SdioLocalCmd52Read1Byte(padapter, offset);
+ else
+ value = rtw_read8(padapter, offset);
+
+ value = value&GET_PWR_CFG_MASK(PwrCfgCmd);
+ if (
+ value == (GET_PWR_CFG_VALUE(PwrCfgCmd) &
+ GET_PWR_CFG_MASK(PwrCfgCmd))
+ )
+ bPollingBit = true;
+ else
+ udelay(10);
+
+ if (pollingCount++ > maxPollingCnt)
+ return false;
+
+ } while (!bPollingBit);
+
+ break;
+
+ case PWR_CMD_DELAY:
+ if (GET_PWR_CFG_VALUE(PwrCfgCmd) == PWRSEQ_DELAY_US)
+ udelay(GET_PWR_CFG_OFFSET(PwrCfgCmd));
+ else
+ udelay(GET_PWR_CFG_OFFSET(PwrCfgCmd)*1000);
+ break;
+
+ case PWR_CMD_END:
+ /* When this command is parsed, end the process */
+ return true;
+
+ default:
+ break;
+ }
+ }
+
+ AryIdx++;/* Add Array Index */
+ } while (1);
+
+ return true;
+}
diff --git a/drivers/staging/rtl8723bs/hal/Mp_Precomp.h b/drivers/staging/rtl8723bs/hal/Mp_Precomp.h
new file mode 100644
index 000000000..f08823a8d
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/Mp_Precomp.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2013 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __MP_PRECOMP_H__
+#define __MP_PRECOMP_H__
+
+#include <drv_types.h>
+#include <hal_data.h>
+
+#define BT_TMP_BUF_SIZE 100
+
+#ifdef bEnable
+#undef bEnable
+#endif
+
+#include "HalBtcOutSrc.h"
+#include "HalBtc8723b1Ant.h"
+#include "HalBtc8723b2Ant.h"
+
+#endif /* __MP_PRECOMP_H__ */
diff --git a/drivers/staging/rtl8723bs/hal/hal_btcoex.c b/drivers/staging/rtl8723bs/hal/hal_btcoex.c
new file mode 100644
index 000000000..e36f8c369
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/hal_btcoex.c
@@ -0,0 +1,1341 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2013 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include <hal_data.h>
+#include <rtw_debug.h>
+#include <hal_btcoex.h>
+#include <Mp_Precomp.h>
+
+/* Global variables */
+
+struct btc_coexist GLBtCoexist;
+static u8 GLBtcWiFiInScanState;
+static u8 GLBtcWiFiInIQKState;
+
+/* */
+/* Debug related function */
+/* */
+static u8 halbtcoutsrc_IsBtCoexistAvailable(struct btc_coexist *pBtCoexist)
+{
+ if (!pBtCoexist->bBinded || !pBtCoexist->Adapter)
+ return false;
+
+ return true;
+}
+
+static void halbtcoutsrc_LeaveLps(struct btc_coexist *pBtCoexist)
+{
+ struct adapter *padapter;
+
+
+ padapter = pBtCoexist->Adapter;
+
+ pBtCoexist->btInfo.bBtCtrlLps = true;
+ pBtCoexist->btInfo.bBtLpsOn = false;
+
+ rtw_btcoex_LPS_Leave(padapter);
+}
+
+static void halbtcoutsrc_EnterLps(struct btc_coexist *pBtCoexist)
+{
+ struct adapter *padapter;
+
+
+ padapter = pBtCoexist->Adapter;
+
+ pBtCoexist->btInfo.bBtCtrlLps = true;
+ pBtCoexist->btInfo.bBtLpsOn = true;
+
+ rtw_btcoex_LPS_Enter(padapter);
+}
+
+static void halbtcoutsrc_NormalLps(struct btc_coexist *pBtCoexist)
+{
+ struct adapter *padapter;
+
+ padapter = pBtCoexist->Adapter;
+
+ if (pBtCoexist->btInfo.bBtCtrlLps) {
+ pBtCoexist->btInfo.bBtLpsOn = false;
+ rtw_btcoex_LPS_Leave(padapter);
+ pBtCoexist->btInfo.bBtCtrlLps = false;
+
+ /* recover the LPS state to the original */
+ }
+}
+
+/*
+ * Constraint:
+ * 1. this function will request pwrctrl->lock
+ */
+static void halbtcoutsrc_LeaveLowPower(struct btc_coexist *pBtCoexist)
+{
+ struct adapter *padapter;
+ s32 ready;
+ unsigned long stime;
+ unsigned long utime;
+ u32 timeout; /* unit: ms */
+
+
+ padapter = pBtCoexist->Adapter;
+ ready = _FAIL;
+#ifdef LPS_RPWM_WAIT_MS
+ timeout = LPS_RPWM_WAIT_MS;
+#else /* !LPS_RPWM_WAIT_MS */
+ timeout = 30;
+#endif /* !LPS_RPWM_WAIT_MS */
+
+ stime = jiffies;
+ do {
+ ready = rtw_register_task_alive(padapter, BTCOEX_ALIVE);
+ if (_SUCCESS == ready)
+ break;
+
+ utime = jiffies_to_msecs(jiffies - stime);
+ if (utime > timeout)
+ break;
+
+ msleep(1);
+ } while (1);
+}
+
+/*
+ * Constraint:
+ * 1. this function will request pwrctrl->lock
+ */
+static void halbtcoutsrc_NormalLowPower(struct btc_coexist *pBtCoexist)
+{
+ struct adapter *padapter;
+
+
+ padapter = pBtCoexist->Adapter;
+ rtw_unregister_task_alive(padapter, BTCOEX_ALIVE);
+}
+
+static void halbtcoutsrc_DisableLowPower(struct btc_coexist *pBtCoexist, u8 bLowPwrDisable)
+{
+ pBtCoexist->btInfo.bBtDisableLowPwr = bLowPwrDisable;
+ if (bLowPwrDisable)
+ halbtcoutsrc_LeaveLowPower(pBtCoexist); /* leave 32k low power. */
+ else
+ halbtcoutsrc_NormalLowPower(pBtCoexist); /* original 32k low power behavior. */
+}
+
+static void halbtcoutsrc_AggregationCheck(struct btc_coexist *pBtCoexist)
+{
+ struct adapter *padapter;
+ bool bNeedToAct;
+
+
+ padapter = pBtCoexist->Adapter;
+ bNeedToAct = false;
+
+ if (pBtCoexist->btInfo.bRejectAggPkt) {
+ rtw_btcoex_RejectApAggregatedPacket(padapter, true);
+ } else {
+ if (pBtCoexist->btInfo.bPreBtCtrlAggBufSize !=
+ pBtCoexist->btInfo.bBtCtrlAggBufSize) {
+ bNeedToAct = true;
+ pBtCoexist->btInfo.bPreBtCtrlAggBufSize = pBtCoexist->btInfo.bBtCtrlAggBufSize;
+ }
+
+ if (pBtCoexist->btInfo.bBtCtrlAggBufSize) {
+ if (pBtCoexist->btInfo.preAggBufSize !=
+ pBtCoexist->btInfo.aggBufSize){
+ bNeedToAct = true;
+ }
+ pBtCoexist->btInfo.preAggBufSize = pBtCoexist->btInfo.aggBufSize;
+ }
+
+ if (bNeedToAct) {
+ rtw_btcoex_RejectApAggregatedPacket(padapter, true);
+ rtw_btcoex_RejectApAggregatedPacket(padapter, false);
+ }
+ }
+}
+
+static u8 halbtcoutsrc_IsWifiBusy(struct adapter *padapter)
+{
+ struct mlme_priv *pmlmepriv;
+
+
+ pmlmepriv = &padapter->mlmepriv;
+
+ if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == true) {
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
+ return true;
+ if (pmlmepriv->LinkDetectInfo.bBusyTraffic)
+ return true;
+ }
+
+ return false;
+}
+
+static u32 _halbtcoutsrc_GetWifiLinkStatus(struct adapter *padapter)
+{
+ struct mlme_priv *pmlmepriv;
+ u8 bp2p;
+ u32 portConnectedStatus;
+
+
+ pmlmepriv = &padapter->mlmepriv;
+ bp2p = false;
+ portConnectedStatus = 0;
+
+ if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == true) {
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
+ if (bp2p)
+ portConnectedStatus |= WIFI_P2P_GO_CONNECTED;
+ else
+ portConnectedStatus |= WIFI_AP_CONNECTED;
+ } else {
+ if (bp2p)
+ portConnectedStatus |= WIFI_P2P_GC_CONNECTED;
+ else
+ portConnectedStatus |= WIFI_STA_CONNECTED;
+ }
+ }
+
+ return portConnectedStatus;
+}
+
+static u32 halbtcoutsrc_GetWifiLinkStatus(struct btc_coexist *pBtCoexist)
+{
+ /* */
+ /* return value: */
+ /* [31:16]=> connected port number */
+ /* [15:0]=> port connected bit define */
+ /* */
+
+ struct adapter *padapter;
+ u32 retVal;
+ u32 portConnectedStatus, numOfConnectedPort;
+
+
+ padapter = pBtCoexist->Adapter;
+ portConnectedStatus = 0;
+ numOfConnectedPort = 0;
+
+ retVal = _halbtcoutsrc_GetWifiLinkStatus(padapter);
+ if (retVal) {
+ portConnectedStatus |= retVal;
+ numOfConnectedPort++;
+ }
+
+ retVal = (numOfConnectedPort << 16) | portConnectedStatus;
+
+ return retVal;
+}
+
+static u32 halbtcoutsrc_GetBtPatchVer(struct btc_coexist *pBtCoexist)
+{
+ return pBtCoexist->btInfo.btRealFwVer;
+}
+
+static s32 halbtcoutsrc_GetWifiRssi(struct adapter *padapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+
+ return pHalData->dmpriv.EntryMinUndecoratedSmoothedPWDB;
+}
+
+static u8 halbtcoutsrc_GetWifiScanAPNum(struct adapter *padapter)
+{
+ struct mlme_ext_priv *pmlmeext;
+ static u8 scan_AP_num;
+
+ pmlmeext = &padapter->mlmeextpriv;
+
+ if (!GLBtcWiFiInScanState) {
+ if (pmlmeext->sitesurvey_res.bss_cnt > 0xFF)
+ scan_AP_num = 0xFF;
+ else
+ scan_AP_num = (u8)pmlmeext->sitesurvey_res.bss_cnt;
+ }
+
+ return scan_AP_num;
+}
+
+static u8 halbtcoutsrc_Get(void *pBtcContext, u8 getType, void *pOutBuf)
+{
+ struct btc_coexist *pBtCoexist;
+ struct adapter *padapter;
+ struct hal_com_data *pHalData;
+ struct mlme_ext_priv *mlmeext;
+ u8 *pu8;
+ s32 *pS4Tmp;
+ u32 *pU4Tmp;
+ u8 ret;
+
+
+ pBtCoexist = (struct btc_coexist *)pBtcContext;
+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
+ return false;
+
+ padapter = pBtCoexist->Adapter;
+ pHalData = GET_HAL_DATA(padapter);
+ mlmeext = &padapter->mlmeextpriv;
+ pu8 = pOutBuf;
+ pS4Tmp = pOutBuf;
+ pU4Tmp = pOutBuf;
+ ret = true;
+
+ switch (getType) {
+ case BTC_GET_BL_HS_OPERATION:
+ *pu8 = false;
+ ret = false;
+ break;
+
+ case BTC_GET_BL_HS_CONNECTING:
+ *pu8 = false;
+ ret = false;
+ break;
+
+ case BTC_GET_BL_WIFI_CONNECTED:
+ *pu8 = check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE);
+ break;
+
+ case BTC_GET_BL_WIFI_BUSY:
+ *pu8 = halbtcoutsrc_IsWifiBusy(padapter);
+ break;
+
+ case BTC_GET_BL_WIFI_SCAN:
+ /* Use the value of the new variable GLBtcWiFiInScanState to judge whether WiFi is in scan state or not, since the originally used flag
+ WIFI_SITE_MONITOR in fwstate may not be cleared in time */
+ *pu8 = GLBtcWiFiInScanState;
+ break;
+
+ case BTC_GET_BL_WIFI_LINK:
+ *pu8 = check_fwstate(&padapter->mlmepriv, WIFI_UNDER_LINKING);
+ break;
+
+ case BTC_GET_BL_WIFI_ROAM:
+ *pu8 = check_fwstate(&padapter->mlmepriv, WIFI_UNDER_LINKING);
+ break;
+
+ case BTC_GET_BL_WIFI_4_WAY_PROGRESS:
+ *pu8 = false;
+ break;
+
+ case BTC_GET_BL_WIFI_AP_MODE_ENABLE:
+ *pu8 = check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE);
+ break;
+
+ case BTC_GET_BL_WIFI_ENABLE_ENCRYPTION:
+ *pu8 = padapter->securitypriv.dot11PrivacyAlgrthm != 0;
+ break;
+
+ case BTC_GET_BL_WIFI_UNDER_B_MODE:
+ if (mlmeext->cur_wireless_mode == WIRELESS_11B)
+ *pu8 = true;
+ else
+ *pu8 = false;
+ break;
+
+ case BTC_GET_BL_WIFI_IS_IN_MP_MODE:
+ *pu8 = false;
+ break;
+
+ case BTC_GET_BL_EXT_SWITCH:
+ *pu8 = false;
+ break;
+
+ case BTC_GET_S4_WIFI_RSSI:
+ *pS4Tmp = halbtcoutsrc_GetWifiRssi(padapter);
+ break;
+
+ case BTC_GET_S4_HS_RSSI:
+ *pS4Tmp = 0;
+ ret = false;
+ break;
+
+ case BTC_GET_U4_WIFI_BW:
+ if (is_legacy_only(mlmeext->cur_wireless_mode))
+ *pU4Tmp = BTC_WIFI_BW_LEGACY;
+ else if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_20)
+ *pU4Tmp = BTC_WIFI_BW_HT20;
+ else
+ *pU4Tmp = BTC_WIFI_BW_HT40;
+ break;
+
+ case BTC_GET_U4_WIFI_TRAFFIC_DIRECTION:
+ {
+ struct rt_link_detect_t *plinkinfo;
+ plinkinfo = &padapter->mlmepriv.LinkDetectInfo;
+
+ if (plinkinfo->NumTxOkInPeriod > plinkinfo->NumRxOkInPeriod)
+ *pU4Tmp = BTC_WIFI_TRAFFIC_TX;
+ else
+ *pU4Tmp = BTC_WIFI_TRAFFIC_RX;
+ }
+ break;
+
+ case BTC_GET_U4_WIFI_FW_VER:
+ *pU4Tmp = pHalData->FirmwareVersion << 16;
+ *pU4Tmp |= pHalData->FirmwareSubVersion;
+ break;
+
+ case BTC_GET_U4_WIFI_LINK_STATUS:
+ *pU4Tmp = halbtcoutsrc_GetWifiLinkStatus(pBtCoexist);
+ break;
+
+ case BTC_GET_U4_BT_PATCH_VER:
+ *pU4Tmp = halbtcoutsrc_GetBtPatchVer(pBtCoexist);
+ break;
+
+ case BTC_GET_U1_WIFI_DOT11_CHNL:
+ *pu8 = padapter->mlmeextpriv.cur_channel;
+ break;
+
+ case BTC_GET_U1_WIFI_CENTRAL_CHNL:
+ *pu8 = pHalData->CurrentChannel;
+ break;
+
+ case BTC_GET_U1_WIFI_HS_CHNL:
+ *pu8 = 0;
+ ret = false;
+ break;
+
+ case BTC_GET_U1_MAC_PHY_MODE:
+ *pu8 = BTC_SMSP;
+/* *pU1Tmp = BTC_DMSP; */
+/* *pU1Tmp = BTC_DMDP; */
+/* *pU1Tmp = BTC_MP_UNKNOWN; */
+ break;
+
+ case BTC_GET_U1_AP_NUM:
+ *pu8 = halbtcoutsrc_GetWifiScanAPNum(padapter);
+ break;
+
+ /* 1Ant =========== */
+ case BTC_GET_U1_LPS_MODE:
+ *pu8 = padapter->dvobj->pwrctl_priv.pwr_mode;
+ break;
+
+ default:
+ ret = false;
+ break;
+ }
+
+ return ret;
+}
+
+static u8 halbtcoutsrc_Set(void *pBtcContext, u8 setType, void *pInBuf)
+{
+ struct btc_coexist *pBtCoexist;
+ struct adapter *padapter;
+ u8 *pu8;
+ u32 *pU4Tmp;
+ u8 ret;
+
+
+ pBtCoexist = (struct btc_coexist *)pBtcContext;
+ padapter = pBtCoexist->Adapter;
+ pu8 = pInBuf;
+ pU4Tmp = pInBuf;
+ ret = true;
+
+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
+ return false;
+
+ switch (setType) {
+ /* set some u8 type variables. */
+ case BTC_SET_BL_BT_DISABLE:
+ pBtCoexist->btInfo.bBtDisabled = *pu8;
+ break;
+
+ case BTC_SET_BL_BT_TRAFFIC_BUSY:
+ pBtCoexist->btInfo.bBtBusy = *pu8;
+ break;
+
+ case BTC_SET_BL_BT_LIMITED_DIG:
+ pBtCoexist->btInfo.bLimitedDig = *pu8;
+ break;
+
+ case BTC_SET_BL_FORCE_TO_ROAM:
+ pBtCoexist->btInfo.bForceToRoam = *pu8;
+ break;
+
+ case BTC_SET_BL_TO_REJ_AP_AGG_PKT:
+ pBtCoexist->btInfo.bRejectAggPkt = *pu8;
+ break;
+
+ case BTC_SET_BL_BT_CTRL_AGG_SIZE:
+ pBtCoexist->btInfo.bBtCtrlAggBufSize = *pu8;
+ break;
+
+ case BTC_SET_BL_INC_SCAN_DEV_NUM:
+ pBtCoexist->btInfo.bIncreaseScanDevNum = *pu8;
+ break;
+
+ case BTC_SET_BL_BT_TX_RX_MASK:
+ pBtCoexist->btInfo.bBtTxRxMask = *pu8;
+ break;
+
+ /* set some u8 type variables. */
+ case BTC_SET_U1_RSSI_ADJ_VAL_FOR_AGC_TABLE_ON:
+ pBtCoexist->btInfo.rssiAdjustForAgcTableOn = *pu8;
+ break;
+
+ case BTC_SET_U1_AGG_BUF_SIZE:
+ pBtCoexist->btInfo.aggBufSize = *pu8;
+ break;
+
+ /* the following are some action which will be triggered */
+ case BTC_SET_ACT_GET_BT_RSSI:
+ ret = false;
+ break;
+
+ case BTC_SET_ACT_AGGREGATE_CTRL:
+ halbtcoutsrc_AggregationCheck(pBtCoexist);
+ break;
+
+ /* 1Ant =========== */
+ /* set some u8 type variables. */
+ case BTC_SET_U1_RSSI_ADJ_VAL_FOR_1ANT_COEX_TYPE:
+ pBtCoexist->btInfo.rssiAdjustFor1AntCoexType = *pu8;
+ break;
+
+ case BTC_SET_U1_LPS_VAL:
+ pBtCoexist->btInfo.lpsVal = *pu8;
+ break;
+
+ case BTC_SET_U1_RPWM_VAL:
+ pBtCoexist->btInfo.rpwmVal = *pu8;
+ break;
+
+ /* the following are some action which will be triggered */
+ case BTC_SET_ACT_LEAVE_LPS:
+ halbtcoutsrc_LeaveLps(pBtCoexist);
+ break;
+
+ case BTC_SET_ACT_ENTER_LPS:
+ halbtcoutsrc_EnterLps(pBtCoexist);
+ break;
+
+ case BTC_SET_ACT_NORMAL_LPS:
+ halbtcoutsrc_NormalLps(pBtCoexist);
+ break;
+
+ case BTC_SET_ACT_DISABLE_LOW_POWER:
+ halbtcoutsrc_DisableLowPower(pBtCoexist, *pu8);
+ break;
+
+ case BTC_SET_ACT_UPDATE_RAMASK:
+ pBtCoexist->btInfo.raMask = *pU4Tmp;
+
+ if (check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE) == true) {
+ struct sta_info *psta;
+ struct wlan_bssid_ex *cur_network;
+
+ cur_network = &padapter->mlmeextpriv.mlmext_info.network;
+ psta = rtw_get_stainfo(&padapter->stapriv, cur_network->mac_address);
+ rtw_hal_update_ra_mask(psta, 0);
+ }
+ break;
+
+ case BTC_SET_ACT_SEND_MIMO_PS:
+ ret = false;
+ break;
+
+ case BTC_SET_ACT_CTRL_BT_INFO:
+ ret = false;
+ break;
+
+ case BTC_SET_ACT_CTRL_BT_COEX:
+ ret = false;
+ break;
+ case BTC_SET_ACT_CTRL_8723B_ANT:
+ ret = false;
+ break;
+ /* */
+ default:
+ ret = false;
+ break;
+ }
+
+ return ret;
+}
+
+/* */
+/* IO related function */
+/* */
+static u8 halbtcoutsrc_Read1Byte(void *pBtcContext, u32 RegAddr)
+{
+ struct btc_coexist *pBtCoexist;
+ struct adapter *padapter;
+
+
+ pBtCoexist = (struct btc_coexist *)pBtcContext;
+ padapter = pBtCoexist->Adapter;
+
+ return rtw_read8(padapter, RegAddr);
+}
+
+static u16 halbtcoutsrc_Read2Byte(void *pBtcContext, u32 RegAddr)
+{
+ struct btc_coexist *pBtCoexist;
+ struct adapter *padapter;
+
+
+ pBtCoexist = (struct btc_coexist *)pBtcContext;
+ padapter = pBtCoexist->Adapter;
+
+ return rtw_read16(padapter, RegAddr);
+}
+
+static u32 halbtcoutsrc_Read4Byte(void *pBtcContext, u32 RegAddr)
+{
+ struct btc_coexist *pBtCoexist;
+ struct adapter *padapter;
+
+
+ pBtCoexist = (struct btc_coexist *)pBtcContext;
+ padapter = pBtCoexist->Adapter;
+
+ return rtw_read32(padapter, RegAddr);
+}
+
+static void halbtcoutsrc_Write1Byte(void *pBtcContext, u32 RegAddr, u8 Data)
+{
+ struct btc_coexist *pBtCoexist;
+ struct adapter *padapter;
+
+
+ pBtCoexist = (struct btc_coexist *)pBtcContext;
+ padapter = pBtCoexist->Adapter;
+
+ rtw_write8(padapter, RegAddr, Data);
+}
+
+static void halbtcoutsrc_BitMaskWrite1Byte(void *pBtcContext, u32 regAddr, u8 bitMask, u8 data1b)
+{
+ struct btc_coexist *pBtCoexist;
+ struct adapter *padapter;
+ u8 originalValue, bitShift;
+ u8 i;
+
+
+ pBtCoexist = (struct btc_coexist *)pBtcContext;
+ padapter = pBtCoexist->Adapter;
+ originalValue = 0;
+ bitShift = 0;
+
+ if (bitMask != 0xFF) {
+ originalValue = rtw_read8(padapter, regAddr);
+
+ for (i = 0; i <= 7; i++) {
+ if ((bitMask >> i) & 0x1)
+ break;
+ }
+ bitShift = i;
+
+ data1b = (originalValue & ~bitMask) | ((data1b << bitShift) & bitMask);
+ }
+
+ rtw_write8(padapter, regAddr, data1b);
+}
+
+static void halbtcoutsrc_Write2Byte(void *pBtcContext, u32 RegAddr, u16 Data)
+{
+ struct btc_coexist *pBtCoexist;
+ struct adapter *padapter;
+
+
+ pBtCoexist = (struct btc_coexist *)pBtcContext;
+ padapter = pBtCoexist->Adapter;
+
+ rtw_write16(padapter, RegAddr, Data);
+}
+
+static void halbtcoutsrc_Write4Byte(void *pBtcContext, u32 RegAddr, u32 Data)
+{
+ struct btc_coexist *pBtCoexist;
+ struct adapter *padapter;
+
+
+ pBtCoexist = (struct btc_coexist *)pBtcContext;
+ padapter = pBtCoexist->Adapter;
+
+ rtw_write32(padapter, RegAddr, Data);
+}
+
+static void halbtcoutsrc_WriteLocalReg1Byte(void *pBtcContext, u32 RegAddr, u8 Data)
+{
+ struct btc_coexist *pBtCoexist = (struct btc_coexist *)pBtcContext;
+ struct adapter *Adapter = pBtCoexist->Adapter;
+
+ if (BTC_INTF_SDIO == pBtCoexist->chipInterface)
+ rtw_write8(Adapter, SDIO_LOCAL_BASE | RegAddr, Data);
+ else
+ rtw_write8(Adapter, RegAddr, Data);
+}
+
+static void halbtcoutsrc_SetBbReg(void *pBtcContext, u32 RegAddr, u32 BitMask, u32 Data)
+{
+ struct btc_coexist *pBtCoexist;
+ struct adapter *padapter;
+
+
+ pBtCoexist = (struct btc_coexist *)pBtcContext;
+ padapter = pBtCoexist->Adapter;
+
+ PHY_SetBBReg(padapter, RegAddr, BitMask, Data);
+}
+
+
+static u32 halbtcoutsrc_GetBbReg(void *pBtcContext, u32 RegAddr, u32 BitMask)
+{
+ struct btc_coexist *pBtCoexist;
+ struct adapter *padapter;
+
+
+ pBtCoexist = (struct btc_coexist *)pBtcContext;
+ padapter = pBtCoexist->Adapter;
+
+ return PHY_QueryBBReg(padapter, RegAddr, BitMask);
+}
+
+static void halbtcoutsrc_SetRfReg(void *pBtcContext, u8 eRFPath, u32 RegAddr, u32 BitMask, u32 Data)
+{
+ struct btc_coexist *pBtCoexist;
+ struct adapter *padapter;
+
+
+ pBtCoexist = (struct btc_coexist *)pBtcContext;
+ padapter = pBtCoexist->Adapter;
+
+ PHY_SetRFReg(padapter, eRFPath, RegAddr, BitMask, Data);
+}
+
+static u32 halbtcoutsrc_GetRfReg(void *pBtcContext, u8 eRFPath, u32 RegAddr, u32 BitMask)
+{
+ struct btc_coexist *pBtCoexist;
+ struct adapter *padapter;
+
+
+ pBtCoexist = (struct btc_coexist *)pBtcContext;
+ padapter = pBtCoexist->Adapter;
+
+ return PHY_QueryRFReg(padapter, eRFPath, RegAddr, BitMask);
+}
+
+static void halbtcoutsrc_SetBtReg(void *pBtcContext, u8 RegType, u32 RegAddr, u32 Data)
+{
+ struct btc_coexist *pBtCoexist;
+ struct adapter *padapter;
+ u8 CmdBuffer1[4] = {0};
+ u8 CmdBuffer2[4] = {0};
+ u8 *AddrToSet = (u8 *)&RegAddr;
+ u8 *ValueToSet = (u8 *)&Data;
+ u8 OperVer = 0;
+ u8 ReqNum = 0;
+
+ pBtCoexist = (struct btc_coexist *)pBtcContext;
+ padapter = pBtCoexist->Adapter;
+
+ CmdBuffer1[0] |= (OperVer & 0x0f); /* Set OperVer */
+ CmdBuffer1[0] |= ((ReqNum << 4) & 0xf0); /* Set ReqNum */
+ CmdBuffer1[1] = 0x0d; /* Set OpCode to BT_LO_OP_WRITE_REG_VALUE */
+ CmdBuffer1[2] = ValueToSet[0]; /* Set WriteRegValue */
+ rtw_hal_fill_h2c_cmd(padapter, 0x67, 4, &(CmdBuffer1[0]));
+
+ msleep(200);
+ ReqNum++;
+
+ CmdBuffer2[0] |= (OperVer & 0x0f); /* Set OperVer */
+ CmdBuffer2[0] |= ((ReqNum << 4) & 0xf0); /* Set ReqNum */
+ CmdBuffer2[1] = 0x0c; /* Set OpCode of BT_LO_OP_WRITE_REG_ADDR */
+ CmdBuffer2[3] = AddrToSet[0]; /* Set WriteRegAddr */
+ rtw_hal_fill_h2c_cmd(padapter, 0x67, 4, &(CmdBuffer2[0]));
+}
+
+static u32 halbtcoutsrc_GetBtReg(void *pBtcContext, u8 RegType, u32 RegAddr)
+{
+ /* To be implemented. Always return 0 temporarily */
+ return 0;
+}
+
+static void halbtcoutsrc_FillH2cCmd(void *pBtcContext, u8 elementId, u32 cmdLen, u8 *pCmdBuffer)
+{
+ struct btc_coexist *pBtCoexist;
+ struct adapter *padapter;
+
+
+ pBtCoexist = (struct btc_coexist *)pBtcContext;
+ padapter = pBtCoexist->Adapter;
+
+ rtw_hal_fill_h2c_cmd(padapter, elementId, cmdLen, pCmdBuffer);
+}
+
+/* */
+/* Extern functions called by other module */
+/* */
+static u8 EXhalbtcoutsrc_BindBtCoexWithAdapter(void *padapter)
+{
+ struct btc_coexist *pBtCoexist = &GLBtCoexist;
+
+ if (pBtCoexist->bBinded)
+ return false;
+ else
+ pBtCoexist->bBinded = true;
+
+ pBtCoexist->statistics.cntBind++;
+
+ pBtCoexist->Adapter = padapter;
+
+ pBtCoexist->stackInfo.bProfileNotified = false;
+
+ pBtCoexist->btInfo.bBtCtrlAggBufSize = false;
+ pBtCoexist->btInfo.aggBufSize = 5;
+
+ pBtCoexist->btInfo.bIncreaseScanDevNum = false;
+
+ /* set default antenna position to main port */
+ pBtCoexist->boardInfo.btdmAntPos = BTC_ANTENNA_AT_MAIN_PORT;
+
+ return true;
+}
+
+void hal_btcoex_Initialize(void *padapter)
+{
+ struct btc_coexist *pBtCoexist;
+
+ memset(&GLBtCoexist, 0, sizeof(GLBtCoexist));
+
+ pBtCoexist = &GLBtCoexist;
+
+ /* pBtCoexist->statistics.cntBind++; */
+
+ pBtCoexist->chipInterface = BTC_INTF_SDIO;
+
+ EXhalbtcoutsrc_BindBtCoexWithAdapter(padapter);
+
+ pBtCoexist->fBtcRead1Byte = halbtcoutsrc_Read1Byte;
+ pBtCoexist->fBtcWrite1Byte = halbtcoutsrc_Write1Byte;
+ pBtCoexist->fBtcWrite1ByteBitMask = halbtcoutsrc_BitMaskWrite1Byte;
+ pBtCoexist->fBtcRead2Byte = halbtcoutsrc_Read2Byte;
+ pBtCoexist->fBtcWrite2Byte = halbtcoutsrc_Write2Byte;
+ pBtCoexist->fBtcRead4Byte = halbtcoutsrc_Read4Byte;
+ pBtCoexist->fBtcWrite4Byte = halbtcoutsrc_Write4Byte;
+ pBtCoexist->fBtcWriteLocalReg1Byte = halbtcoutsrc_WriteLocalReg1Byte;
+
+ pBtCoexist->fBtcSetBbReg = halbtcoutsrc_SetBbReg;
+ pBtCoexist->fBtcGetBbReg = halbtcoutsrc_GetBbReg;
+
+ pBtCoexist->fBtcSetRfReg = halbtcoutsrc_SetRfReg;
+ pBtCoexist->fBtcGetRfReg = halbtcoutsrc_GetRfReg;
+
+ pBtCoexist->fBtcFillH2c = halbtcoutsrc_FillH2cCmd;
+
+ pBtCoexist->fBtcGet = halbtcoutsrc_Get;
+ pBtCoexist->fBtcSet = halbtcoutsrc_Set;
+ pBtCoexist->fBtcGetBtReg = halbtcoutsrc_GetBtReg;
+ pBtCoexist->fBtcSetBtReg = halbtcoutsrc_SetBtReg;
+
+ pBtCoexist->boardInfo.singleAntPath = 0;
+
+ GLBtcWiFiInScanState = false;
+
+ GLBtcWiFiInIQKState = false;
+}
+
+void EXhalbtcoutsrc_PowerOnSetting(struct btc_coexist *pBtCoexist)
+{
+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
+ return;
+
+ /* Power on setting function is only added in 8723B currently */
+ if (pBtCoexist->boardInfo.btdmAntNum == 2)
+ EXhalbtc8723b2ant_PowerOnSetting(pBtCoexist);
+ else if (pBtCoexist->boardInfo.btdmAntNum == 1)
+ EXhalbtc8723b1ant_PowerOnSetting(pBtCoexist);
+}
+
+void EXhalbtcoutsrc_InitHwConfig(struct btc_coexist *pBtCoexist, u8 bWifiOnly)
+{
+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
+ return;
+
+ pBtCoexist->statistics.cntInitHwConfig++;
+
+ if (pBtCoexist->boardInfo.btdmAntNum == 2)
+ EXhalbtc8723b2ant_InitHwConfig(pBtCoexist, bWifiOnly);
+ else if (pBtCoexist->boardInfo.btdmAntNum == 1)
+ EXhalbtc8723b1ant_InitHwConfig(pBtCoexist, bWifiOnly);
+}
+
+void EXhalbtcoutsrc_InitCoexDm(struct btc_coexist *pBtCoexist)
+{
+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
+ return;
+
+ pBtCoexist->statistics.cntInitCoexDm++;
+
+ if (pBtCoexist->boardInfo.btdmAntNum == 2)
+ EXhalbtc8723b2ant_InitCoexDm(pBtCoexist);
+ else if (pBtCoexist->boardInfo.btdmAntNum == 1)
+ EXhalbtc8723b1ant_InitCoexDm(pBtCoexist);
+
+ pBtCoexist->bInitilized = true;
+}
+
+void EXhalbtcoutsrc_IpsNotify(struct btc_coexist *pBtCoexist, u8 type)
+{
+ u8 ipsType;
+
+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
+ return;
+
+ pBtCoexist->statistics.cntIpsNotify++;
+ if (pBtCoexist->bManualControl)
+ return;
+
+ if (IPS_NONE == type)
+ ipsType = BTC_IPS_LEAVE;
+ else
+ ipsType = BTC_IPS_ENTER;
+
+ /* All notify is called in cmd thread, don't need to leave low power again */
+/* halbtcoutsrc_LeaveLowPower(pBtCoexist); */
+
+ if (pBtCoexist->boardInfo.btdmAntNum == 2)
+ EXhalbtc8723b2ant_IpsNotify(pBtCoexist, ipsType);
+ else if (pBtCoexist->boardInfo.btdmAntNum == 1)
+ EXhalbtc8723b1ant_IpsNotify(pBtCoexist, ipsType);
+
+/* halbtcoutsrc_NormalLowPower(pBtCoexist); */
+}
+
+void EXhalbtcoutsrc_LpsNotify(struct btc_coexist *pBtCoexist, u8 type)
+{
+ u8 lpsType;
+
+
+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
+ return;
+
+ pBtCoexist->statistics.cntLpsNotify++;
+ if (pBtCoexist->bManualControl)
+ return;
+
+ if (PS_MODE_ACTIVE == type)
+ lpsType = BTC_LPS_DISABLE;
+ else
+ lpsType = BTC_LPS_ENABLE;
+
+ if (pBtCoexist->boardInfo.btdmAntNum == 2)
+ EXhalbtc8723b2ant_LpsNotify(pBtCoexist, lpsType);
+ else if (pBtCoexist->boardInfo.btdmAntNum == 1)
+ EXhalbtc8723b1ant_LpsNotify(pBtCoexist, lpsType);
+}
+
+void EXhalbtcoutsrc_ScanNotify(struct btc_coexist *pBtCoexist, u8 type)
+{
+ u8 scanType;
+
+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
+ return;
+ pBtCoexist->statistics.cntScanNotify++;
+ if (pBtCoexist->bManualControl)
+ return;
+
+ if (type) {
+ scanType = BTC_SCAN_START;
+ GLBtcWiFiInScanState = true;
+ } else {
+ scanType = BTC_SCAN_FINISH;
+ GLBtcWiFiInScanState = false;
+ }
+
+ /* All notify is called in cmd thread, don't need to leave low power again */
+/* halbtcoutsrc_LeaveLowPower(pBtCoexist); */
+
+ if (pBtCoexist->boardInfo.btdmAntNum == 2)
+ EXhalbtc8723b2ant_ScanNotify(pBtCoexist, scanType);
+ else if (pBtCoexist->boardInfo.btdmAntNum == 1)
+ EXhalbtc8723b1ant_ScanNotify(pBtCoexist, scanType);
+
+/* halbtcoutsrc_NormalLowPower(pBtCoexist); */
+}
+
+void EXhalbtcoutsrc_ConnectNotify(struct btc_coexist *pBtCoexist, u8 action)
+{
+ u8 assoType;
+
+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
+ return;
+ pBtCoexist->statistics.cntConnectNotify++;
+ if (pBtCoexist->bManualControl)
+ return;
+
+ if (action)
+ assoType = BTC_ASSOCIATE_START;
+ else
+ assoType = BTC_ASSOCIATE_FINISH;
+
+ /* All notify is called in cmd thread, don't need to leave low power again */
+/* halbtcoutsrc_LeaveLowPower(pBtCoexist); */
+
+ if (pBtCoexist->boardInfo.btdmAntNum == 2)
+ EXhalbtc8723b2ant_ConnectNotify(pBtCoexist, assoType);
+ else if (pBtCoexist->boardInfo.btdmAntNum == 1)
+ EXhalbtc8723b1ant_ConnectNotify(pBtCoexist, assoType);
+
+/* halbtcoutsrc_NormalLowPower(pBtCoexist); */
+}
+
+void EXhalbtcoutsrc_MediaStatusNotify(struct btc_coexist *pBtCoexist, enum
+ rt_media_status mediaStatus)
+{
+ u8 mStatus;
+
+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
+ return;
+
+ pBtCoexist->statistics.cntMediaStatusNotify++;
+ if (pBtCoexist->bManualControl)
+ return;
+
+ if (RT_MEDIA_CONNECT == mediaStatus)
+ mStatus = BTC_MEDIA_CONNECT;
+ else
+ mStatus = BTC_MEDIA_DISCONNECT;
+
+ /* All notify is called in cmd thread, don't need to leave low power again */
+/* halbtcoutsrc_LeaveLowPower(pBtCoexist); */
+
+ if (pBtCoexist->boardInfo.btdmAntNum == 2)
+ EXhalbtc8723b2ant_MediaStatusNotify(pBtCoexist, mStatus);
+ else if (pBtCoexist->boardInfo.btdmAntNum == 1)
+ EXhalbtc8723b1ant_MediaStatusNotify(pBtCoexist, mStatus);
+
+/* halbtcoutsrc_NormalLowPower(pBtCoexist); */
+}
+
+void EXhalbtcoutsrc_SpecialPacketNotify(struct btc_coexist *pBtCoexist, u8 pktType)
+{
+ u8 packetType;
+
+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
+ return;
+ pBtCoexist->statistics.cntSpecialPacketNotify++;
+ if (pBtCoexist->bManualControl)
+ return;
+
+ if (PACKET_DHCP == pktType) {
+ packetType = BTC_PACKET_DHCP;
+ } else if (PACKET_EAPOL == pktType) {
+ packetType = BTC_PACKET_EAPOL;
+ } else if (PACKET_ARP == pktType) {
+ packetType = BTC_PACKET_ARP;
+ } else {
+ return;
+ }
+
+ /* All notify is called in cmd thread, don't need to leave low power again */
+/* halbtcoutsrc_LeaveLowPower(pBtCoexist); */
+
+ if (pBtCoexist->boardInfo.btdmAntNum == 2)
+ EXhalbtc8723b2ant_SpecialPacketNotify(pBtCoexist, packetType);
+ else if (pBtCoexist->boardInfo.btdmAntNum == 1)
+ EXhalbtc8723b1ant_SpecialPacketNotify(pBtCoexist, packetType);
+
+/* halbtcoutsrc_NormalLowPower(pBtCoexist); */
+}
+
+void EXhalbtcoutsrc_BtInfoNotify(struct btc_coexist *pBtCoexist, u8 *tmpBuf, u8 length)
+{
+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
+ return;
+
+ pBtCoexist->statistics.cntBtInfoNotify++;
+
+ /* All notify is called in cmd thread, don't need to leave low power again */
+/* halbtcoutsrc_LeaveLowPower(pBtCoexist); */
+
+ if (pBtCoexist->boardInfo.btdmAntNum == 2)
+ EXhalbtc8723b2ant_BtInfoNotify(pBtCoexist, tmpBuf, length);
+ else if (pBtCoexist->boardInfo.btdmAntNum == 1)
+ EXhalbtc8723b1ant_BtInfoNotify(pBtCoexist, tmpBuf, length);
+
+/* halbtcoutsrc_NormalLowPower(pBtCoexist); */
+}
+
+void EXhalbtcoutsrc_HaltNotify(struct btc_coexist *pBtCoexist)
+{
+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
+ return;
+
+ if (pBtCoexist->boardInfo.btdmAntNum == 2)
+ EXhalbtc8723b2ant_HaltNotify(pBtCoexist);
+ else if (pBtCoexist->boardInfo.btdmAntNum == 1)
+ EXhalbtc8723b1ant_HaltNotify(pBtCoexist);
+
+ pBtCoexist->bBinded = false;
+}
+
+void EXhalbtcoutsrc_PnpNotify(struct btc_coexist *pBtCoexist, u8 pnpState)
+{
+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
+ return;
+
+ /* */
+ /* currently only 1ant we have to do the notification, */
+ /* once pnp is notified to sleep state, we have to leave LPS that we can sleep normally. */
+ /* */
+
+ if (pBtCoexist->boardInfo.btdmAntNum == 1)
+ EXhalbtc8723b1ant_PnpNotify(pBtCoexist, pnpState);
+ else if (pBtCoexist->boardInfo.btdmAntNum == 2)
+ EXhalbtc8723b2ant_PnpNotify(pBtCoexist, pnpState);
+}
+
+void EXhalbtcoutsrc_Periodical(struct btc_coexist *pBtCoexist)
+{
+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
+ return;
+ pBtCoexist->statistics.cntPeriodical++;
+
+ /* Periodical should be called in cmd thread, */
+ /* don't need to leave low power again */
+/* halbtcoutsrc_LeaveLowPower(pBtCoexist); */
+
+ if (pBtCoexist->boardInfo.btdmAntNum == 2)
+ EXhalbtc8723b2ant_Periodical(pBtCoexist);
+ else if (pBtCoexist->boardInfo.btdmAntNum == 1)
+ EXhalbtc8723b1ant_Periodical(pBtCoexist);
+
+/* halbtcoutsrc_NormalLowPower(pBtCoexist); */
+}
+
+void EXhalbtcoutsrc_SetAntNum(u8 type, u8 antNum)
+{
+ if (BT_COEX_ANT_TYPE_PG == type) {
+ GLBtCoexist.boardInfo.pgAntNum = antNum;
+ GLBtCoexist.boardInfo.btdmAntNum = antNum;
+ } else if (BT_COEX_ANT_TYPE_ANTDIV == type) {
+ GLBtCoexist.boardInfo.btdmAntNum = antNum;
+ /* GLBtCoexist.boardInfo.btdmAntPos = BTC_ANTENNA_AT_MAIN_PORT; */
+ } else if (BT_COEX_ANT_TYPE_DETECTED == type) {
+ GLBtCoexist.boardInfo.btdmAntNum = antNum;
+ /* GLBtCoexist.boardInfo.btdmAntPos = BTC_ANTENNA_AT_MAIN_PORT; */
+ }
+}
+
+/* */
+/* Currently used by 8723b only, S0 or S1 */
+/* */
+void EXhalbtcoutsrc_SetSingleAntPath(u8 singleAntPath)
+{
+ GLBtCoexist.boardInfo.singleAntPath = singleAntPath;
+}
+
+/*
+ * Description:
+ *Run BT-Coexist mechanism or not
+ *
+ */
+void hal_btcoex_SetBTCoexist(struct adapter *padapter, u8 bBtExist)
+{
+ struct hal_com_data *pHalData;
+
+
+ pHalData = GET_HAL_DATA(padapter);
+ pHalData->bt_coexist.bBtExist = bBtExist;
+}
+
+/*
+ * Dewcription:
+ *Check is co-exist mechanism enabled or not
+ *
+ * Return:
+ *true Enable BT co-exist mechanism
+ *false Disable BT co-exist mechanism
+ */
+bool hal_btcoex_IsBtExist(struct adapter *padapter)
+{
+ struct hal_com_data *pHalData;
+
+
+ pHalData = GET_HAL_DATA(padapter);
+ return pHalData->bt_coexist.bBtExist;
+}
+
+bool hal_btcoex_IsBtDisabled(struct adapter *padapter)
+{
+ if (!hal_btcoex_IsBtExist(padapter))
+ return true;
+
+ if (GLBtCoexist.btInfo.bBtDisabled)
+ return true;
+ else
+ return false;
+}
+
+void hal_btcoex_SetChipType(struct adapter *padapter, u8 chipType)
+{
+ struct hal_com_data *pHalData;
+
+
+ pHalData = GET_HAL_DATA(padapter);
+}
+
+void hal_btcoex_SetPgAntNum(struct adapter *padapter, u8 antNum)
+{
+ struct hal_com_data *pHalData;
+
+
+ pHalData = GET_HAL_DATA(padapter);
+
+ pHalData->bt_coexist.btTotalAntNum = antNum;
+ EXhalbtcoutsrc_SetAntNum(BT_COEX_ANT_TYPE_PG, antNum);
+}
+
+void hal_btcoex_SetSingleAntPath(struct adapter *padapter, u8 singleAntPath)
+{
+ EXhalbtcoutsrc_SetSingleAntPath(singleAntPath);
+}
+
+void hal_btcoex_PowerOnSetting(struct adapter *padapter)
+{
+ EXhalbtcoutsrc_PowerOnSetting(&GLBtCoexist);
+}
+
+void hal_btcoex_InitHwConfig(struct adapter *padapter, u8 bWifiOnly)
+{
+ if (!hal_btcoex_IsBtExist(padapter))
+ return;
+
+ EXhalbtcoutsrc_InitHwConfig(&GLBtCoexist, bWifiOnly);
+ EXhalbtcoutsrc_InitCoexDm(&GLBtCoexist);
+}
+
+void hal_btcoex_IpsNotify(struct adapter *padapter, u8 type)
+{
+ EXhalbtcoutsrc_IpsNotify(&GLBtCoexist, type);
+}
+
+void hal_btcoex_LpsNotify(struct adapter *padapter, u8 type)
+{
+ EXhalbtcoutsrc_LpsNotify(&GLBtCoexist, type);
+}
+
+void hal_btcoex_ScanNotify(struct adapter *padapter, u8 type)
+{
+ EXhalbtcoutsrc_ScanNotify(&GLBtCoexist, type);
+}
+
+void hal_btcoex_ConnectNotify(struct adapter *padapter, u8 action)
+{
+ EXhalbtcoutsrc_ConnectNotify(&GLBtCoexist, action);
+}
+
+void hal_btcoex_MediaStatusNotify(struct adapter *padapter, u8 mediaStatus)
+{
+ EXhalbtcoutsrc_MediaStatusNotify(&GLBtCoexist, mediaStatus);
+}
+
+void hal_btcoex_SpecialPacketNotify(struct adapter *padapter, u8 pktType)
+{
+ EXhalbtcoutsrc_SpecialPacketNotify(&GLBtCoexist, pktType);
+}
+
+void hal_btcoex_IQKNotify(struct adapter *padapter, u8 state)
+{
+ GLBtcWiFiInIQKState = state;
+}
+
+void hal_btcoex_BtInfoNotify(struct adapter *padapter, u8 length, u8 *tmpBuf)
+{
+ if (GLBtcWiFiInIQKState)
+ return;
+
+ EXhalbtcoutsrc_BtInfoNotify(&GLBtCoexist, tmpBuf, length);
+}
+
+void hal_btcoex_SuspendNotify(struct adapter *padapter, u8 state)
+{
+ if (state == 1)
+ state = BTC_WIFI_PNP_SLEEP;
+ else
+ state = BTC_WIFI_PNP_WAKE_UP;
+
+ EXhalbtcoutsrc_PnpNotify(&GLBtCoexist, state);
+}
+
+void hal_btcoex_HaltNotify(struct adapter *padapter)
+{
+ EXhalbtcoutsrc_HaltNotify(&GLBtCoexist);
+}
+
+void hal_btcoex_Handler(struct adapter *padapter)
+{
+ EXhalbtcoutsrc_Periodical(&GLBtCoexist);
+}
+
+s32 hal_btcoex_IsBTCoexCtrlAMPDUSize(struct adapter *padapter)
+{
+ return (s32)GLBtCoexist.btInfo.bBtCtrlAggBufSize;
+}
+
+bool hal_btcoex_IsBtControlLps(struct adapter *padapter)
+{
+ if (!hal_btcoex_IsBtExist(padapter))
+ return false;
+
+ if (GLBtCoexist.btInfo.bBtDisabled)
+ return false;
+
+ if (GLBtCoexist.btInfo.bBtCtrlLps)
+ return true;
+
+ return false;
+}
+
+bool hal_btcoex_IsLpsOn(struct adapter *padapter)
+{
+ if (!hal_btcoex_IsBtExist(padapter))
+ return false;
+
+ if (GLBtCoexist.btInfo.bBtDisabled)
+ return false;
+
+ if (GLBtCoexist.btInfo.bBtLpsOn)
+ return true;
+
+ return false;
+}
+
+u8 hal_btcoex_RpwmVal(struct adapter *padapter)
+{
+ return GLBtCoexist.btInfo.rpwmVal;
+}
+
+u8 hal_btcoex_LpsVal(struct adapter *padapter)
+{
+ return GLBtCoexist.btInfo.lpsVal;
+}
+
+u32 hal_btcoex_GetRaMask(struct adapter *padapter)
+{
+ if (!hal_btcoex_IsBtExist(padapter))
+ return 0;
+
+ if (GLBtCoexist.btInfo.bBtDisabled)
+ return 0;
+
+ if (GLBtCoexist.boardInfo.btdmAntNum != 1)
+ return 0;
+
+ return GLBtCoexist.btInfo.raMask;
+}
+
+void hal_btcoex_RecordPwrMode(struct adapter *padapter, u8 *pCmdBuf, u8 cmdLen)
+{
+ memcpy(GLBtCoexist.pwrModeVal, pCmdBuf, cmdLen);
+}
diff --git a/drivers/staging/rtl8723bs/hal/hal_com.c b/drivers/staging/rtl8723bs/hal/hal_com.c
new file mode 100644
index 000000000..e42556d03
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/hal_com.c
@@ -0,0 +1,1096 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include <linux/kernel.h>
+#include <drv_types.h>
+#include <rtw_debug.h>
+#include "hal_com_h2c.h"
+
+#include "odm_precomp.h"
+
+u8 rtw_hal_data_init(struct adapter *padapter)
+{
+ if (is_primary_adapter(padapter)) { /* if (padapter->isprimary) */
+ padapter->hal_data_sz = sizeof(struct hal_com_data);
+ padapter->HalData = vzalloc(padapter->hal_data_sz);
+ if (!padapter->HalData)
+ return _FAIL;
+ }
+ return _SUCCESS;
+}
+
+void rtw_hal_data_deinit(struct adapter *padapter)
+{
+ if (is_primary_adapter(padapter)) { /* if (padapter->isprimary) */
+ if (padapter->HalData) {
+ vfree(padapter->HalData);
+ padapter->HalData = NULL;
+ padapter->hal_data_sz = 0;
+ }
+ }
+}
+
+
+void dump_chip_info(struct hal_version ChipVersion)
+{
+ char buf[128];
+ size_t cnt = 0;
+
+ cnt += scnprintf(buf + cnt, sizeof(buf) - cnt, "Chip Version Info: CHIP_8723B_%s_",
+ IS_NORMAL_CHIP(ChipVersion) ? "Normal_Chip" : "Test_Chip");
+
+ if (IS_CHIP_VENDOR_TSMC(ChipVersion))
+ cnt += scnprintf(buf + cnt, sizeof(buf) - cnt, "TSMC_");
+ else if (IS_CHIP_VENDOR_UMC(ChipVersion))
+ cnt += scnprintf(buf + cnt, sizeof(buf) - cnt, "UMC_");
+ else if (IS_CHIP_VENDOR_SMIC(ChipVersion))
+ cnt += scnprintf(buf + cnt, sizeof(buf) - cnt, "SMIC_");
+
+ if (IS_A_CUT(ChipVersion))
+ cnt += scnprintf(buf + cnt, sizeof(buf) - cnt, "A_CUT_");
+ else if (IS_B_CUT(ChipVersion))
+ cnt += scnprintf(buf + cnt, sizeof(buf) - cnt, "B_CUT_");
+ else if (IS_C_CUT(ChipVersion))
+ cnt += scnprintf(buf + cnt, sizeof(buf) - cnt, "C_CUT_");
+ else if (IS_D_CUT(ChipVersion))
+ cnt += scnprintf(buf + cnt, sizeof(buf) - cnt, "D_CUT_");
+ else if (IS_E_CUT(ChipVersion))
+ cnt += scnprintf(buf + cnt, sizeof(buf) - cnt, "E_CUT_");
+ else if (IS_I_CUT(ChipVersion))
+ cnt += scnprintf(buf + cnt, sizeof(buf) - cnt, "I_CUT_");
+ else if (IS_J_CUT(ChipVersion))
+ cnt += scnprintf(buf + cnt, sizeof(buf) - cnt, "J_CUT_");
+ else if (IS_K_CUT(ChipVersion))
+ cnt += scnprintf(buf + cnt, sizeof(buf) - cnt, "K_CUT_");
+ else
+ cnt += scnprintf(buf + cnt, sizeof(buf) - cnt,
+ "UNKNOWN_CUT(%d)_", ChipVersion.CUTVersion);
+
+ cnt += scnprintf(buf + cnt, sizeof(buf) - cnt, "1T1R_");
+
+ cnt += scnprintf(buf + cnt, sizeof(buf) - cnt, "RomVer(%d)\n", ChipVersion.ROMVer);
+}
+
+
+#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80
+
+/*
+ * Description:
+ *Use hardware(efuse), driver parameter(registry) and default channel plan
+ *to decide which one should be used.
+ *
+ * Parameters:
+ *padapter pointer of adapter
+ *hw_channel_plan channel plan from HW (efuse/eeprom)
+ * BIT[7] software configure mode; 0:Enable, 1:disable
+ * BIT[6:0] Channel Plan
+ *sw_channel_plan channel plan from SW (registry/module param)
+ *def_channel_plan channel plan used when HW/SW both invalid
+ *AutoLoadFail efuse autoload fail or not
+ *
+ * Return:
+ *Final channel plan decision
+ *
+ */
+u8 hal_com_config_channel_plan(
+ struct adapter *padapter,
+ u8 hw_channel_plan,
+ u8 sw_channel_plan,
+ u8 def_channel_plan,
+ bool AutoLoadFail
+)
+{
+ struct hal_com_data *pHalData;
+ u8 chnlPlan;
+
+ pHalData = GET_HAL_DATA(padapter);
+ pHalData->bDisableSWChannelPlan = false;
+ chnlPlan = def_channel_plan;
+
+ if (0xFF == hw_channel_plan)
+ AutoLoadFail = true;
+
+ if (!AutoLoadFail) {
+ u8 hw_chnlPlan;
+
+ hw_chnlPlan = hw_channel_plan & (~EEPROM_CHANNEL_PLAN_BY_HW_MASK);
+ if (rtw_is_channel_plan_valid(hw_chnlPlan)) {
+ if (hw_channel_plan & EEPROM_CHANNEL_PLAN_BY_HW_MASK)
+ pHalData->bDisableSWChannelPlan = true;
+
+ chnlPlan = hw_chnlPlan;
+ }
+ }
+
+ if (
+ (false == pHalData->bDisableSWChannelPlan) &&
+ rtw_is_channel_plan_valid(sw_channel_plan)
+ )
+ chnlPlan = sw_channel_plan;
+
+ return chnlPlan;
+}
+
+bool HAL_IsLegalChannel(struct adapter *adapter, u32 Channel)
+{
+ bool bLegalChannel = true;
+
+ if ((Channel <= 14) && (Channel >= 1)) {
+ if (is_supported_24g(adapter->registrypriv.wireless_mode) == false)
+ bLegalChannel = false;
+ } else {
+ bLegalChannel = false;
+ }
+
+ return bLegalChannel;
+}
+
+u8 MRateToHwRate(u8 rate)
+{
+ u8 ret = DESC_RATE1M;
+
+ switch (rate) {
+ case MGN_1M:
+ ret = DESC_RATE1M;
+ break;
+ case MGN_2M:
+ ret = DESC_RATE2M;
+ break;
+ case MGN_5_5M:
+ ret = DESC_RATE5_5M;
+ break;
+ case MGN_11M:
+ ret = DESC_RATE11M;
+ break;
+ case MGN_6M:
+ ret = DESC_RATE6M;
+ break;
+ case MGN_9M:
+ ret = DESC_RATE9M;
+ break;
+ case MGN_12M:
+ ret = DESC_RATE12M;
+ break;
+ case MGN_18M:
+ ret = DESC_RATE18M;
+ break;
+ case MGN_24M:
+ ret = DESC_RATE24M;
+ break;
+ case MGN_36M:
+ ret = DESC_RATE36M;
+ break;
+ case MGN_48M:
+ ret = DESC_RATE48M;
+ break;
+ case MGN_54M:
+ ret = DESC_RATE54M;
+ break;
+ case MGN_MCS0:
+ ret = DESC_RATEMCS0;
+ break;
+ case MGN_MCS1:
+ ret = DESC_RATEMCS1;
+ break;
+ case MGN_MCS2:
+ ret = DESC_RATEMCS2;
+ break;
+ case MGN_MCS3:
+ ret = DESC_RATEMCS3;
+ break;
+ case MGN_MCS4:
+ ret = DESC_RATEMCS4;
+ break;
+ case MGN_MCS5:
+ ret = DESC_RATEMCS5;
+ break;
+ case MGN_MCS6:
+ ret = DESC_RATEMCS6;
+ break;
+ case MGN_MCS7:
+ ret = DESC_RATEMCS7;
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+u8 HwRateToMRate(u8 rate)
+{
+ u8 ret_rate = MGN_1M;
+
+ switch (rate) {
+ case DESC_RATE1M:
+ ret_rate = MGN_1M;
+ break;
+ case DESC_RATE2M:
+ ret_rate = MGN_2M;
+ break;
+ case DESC_RATE5_5M:
+ ret_rate = MGN_5_5M;
+ break;
+ case DESC_RATE11M:
+ ret_rate = MGN_11M;
+ break;
+ case DESC_RATE6M:
+ ret_rate = MGN_6M;
+ break;
+ case DESC_RATE9M:
+ ret_rate = MGN_9M;
+ break;
+ case DESC_RATE12M:
+ ret_rate = MGN_12M;
+ break;
+ case DESC_RATE18M:
+ ret_rate = MGN_18M;
+ break;
+ case DESC_RATE24M:
+ ret_rate = MGN_24M;
+ break;
+ case DESC_RATE36M:
+ ret_rate = MGN_36M;
+ break;
+ case DESC_RATE48M:
+ ret_rate = MGN_48M;
+ break;
+ case DESC_RATE54M:
+ ret_rate = MGN_54M;
+ break;
+ case DESC_RATEMCS0:
+ ret_rate = MGN_MCS0;
+ break;
+ case DESC_RATEMCS1:
+ ret_rate = MGN_MCS1;
+ break;
+ case DESC_RATEMCS2:
+ ret_rate = MGN_MCS2;
+ break;
+ case DESC_RATEMCS3:
+ ret_rate = MGN_MCS3;
+ break;
+ case DESC_RATEMCS4:
+ ret_rate = MGN_MCS4;
+ break;
+ case DESC_RATEMCS5:
+ ret_rate = MGN_MCS5;
+ break;
+ case DESC_RATEMCS6:
+ ret_rate = MGN_MCS6;
+ break;
+ case DESC_RATEMCS7:
+ ret_rate = MGN_MCS7;
+ break;
+ default:
+ break;
+ }
+
+ return ret_rate;
+}
+
+void HalSetBrateCfg(struct adapter *Adapter, u8 *mBratesOS, u16 *pBrateCfg)
+{
+ u8 i, is_brate, brate;
+
+ for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
+
+ is_brate = mBratesOS[i] & IEEE80211_BASIC_RATE_MASK;
+ brate = mBratesOS[i] & 0x7f;
+
+ if (is_brate) {
+ switch (brate) {
+ case IEEE80211_CCK_RATE_1MB:
+ *pBrateCfg |= RATE_1M;
+ break;
+ case IEEE80211_CCK_RATE_2MB:
+ *pBrateCfg |= RATE_2M;
+ break;
+ case IEEE80211_CCK_RATE_5MB:
+ *pBrateCfg |= RATE_5_5M;
+ break;
+ case IEEE80211_CCK_RATE_11MB:
+ *pBrateCfg |= RATE_11M;
+ break;
+ case IEEE80211_OFDM_RATE_6MB:
+ *pBrateCfg |= RATE_6M;
+ break;
+ case IEEE80211_OFDM_RATE_9MB:
+ *pBrateCfg |= RATE_9M;
+ break;
+ case IEEE80211_OFDM_RATE_12MB:
+ *pBrateCfg |= RATE_12M;
+ break;
+ case IEEE80211_OFDM_RATE_18MB:
+ *pBrateCfg |= RATE_18M;
+ break;
+ case IEEE80211_OFDM_RATE_24MB:
+ *pBrateCfg |= RATE_24M;
+ break;
+ case IEEE80211_OFDM_RATE_36MB:
+ *pBrateCfg |= RATE_36M;
+ break;
+ case IEEE80211_OFDM_RATE_48MB:
+ *pBrateCfg |= RATE_48M;
+ break;
+ case IEEE80211_OFDM_RATE_54MB:
+ *pBrateCfg |= RATE_54M;
+ break;
+ }
+ }
+ }
+}
+
+static void _OneOutPipeMapping(struct adapter *padapter)
+{
+ struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
+
+ pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */
+ pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0];/* VI */
+ pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[0];/* BE */
+ pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0];/* BK */
+
+ pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */
+ pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
+ pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */
+ pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
+}
+
+static void _TwoOutPipeMapping(struct adapter *padapter, bool bWIFICfg)
+{
+ struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
+
+ if (bWIFICfg) { /* WMM */
+
+ /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
+ /* 0, 1, 0, 1, 0, 0, 0, 0, 0 }; */
+ /* 0:ep_0 num, 1:ep_1 num */
+
+ pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[1];/* VO */
+ pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0];/* VI */
+ pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1];/* BE */
+ pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0];/* BK */
+
+ pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */
+ pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
+ pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */
+ pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
+
+ } else { /* typical setting */
+
+
+ /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
+ /* 1, 1, 0, 0, 0, 0, 0, 0, 0 }; */
+ /* 0:ep_0 num, 1:ep_1 num */
+
+ pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */
+ pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0];/* VI */
+ pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1];/* BE */
+ pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1];/* BK */
+
+ pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */
+ pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
+ pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */
+ pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
+
+ }
+
+}
+
+static void _ThreeOutPipeMapping(struct adapter *padapter, bool bWIFICfg)
+{
+ struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
+
+ if (bWIFICfg) { /* for WMM */
+
+ /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
+ /* 1, 2, 1, 0, 0, 0, 0, 0, 0 }; */
+ /* 0:H, 1:N, 2:L */
+
+ pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */
+ pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1];/* VI */
+ pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2];/* BE */
+ pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1];/* BK */
+
+ pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */
+ pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
+ pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */
+ pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
+
+ } else { /* typical setting */
+
+
+ /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
+ /* 2, 2, 1, 0, 0, 0, 0, 0, 0 }; */
+ /* 0:H, 1:N, 2:L */
+
+ pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */
+ pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1];/* VI */
+ pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2];/* BE */
+ pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[2];/* BK */
+
+ pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */
+ pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
+ pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */
+ pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
+ }
+
+}
+
+bool Hal_MappingOutPipe(struct adapter *padapter, u8 NumOutPipe)
+{
+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
+
+ bool bWIFICfg = (pregistrypriv->wifi_spec) ? true : false;
+
+ bool result = true;
+
+ switch (NumOutPipe) {
+ case 2:
+ _TwoOutPipeMapping(padapter, bWIFICfg);
+ break;
+ case 3:
+ case 4:
+ _ThreeOutPipeMapping(padapter, bWIFICfg);
+ break;
+ case 1:
+ _OneOutPipeMapping(padapter);
+ break;
+ default:
+ result = false;
+ break;
+ }
+
+ return result;
+
+}
+
+void hal_init_macaddr(struct adapter *adapter)
+{
+ rtw_hal_set_hwreg(adapter, HW_VAR_MAC_ADDR, adapter->eeprompriv.mac_addr);
+}
+
+void rtw_init_hal_com_default_value(struct adapter *Adapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+
+ pHalData->AntDetection = 1;
+}
+
+/*
+* C2H event format:
+* Field TRIGGER CONTENT CMD_SEQ CMD_LEN CMD_ID
+* BITS [127:120] [119:16] [15:8] [7:4] [3:0]
+*/
+
+void c2h_evt_clear(struct adapter *adapter)
+{
+ rtw_write8(adapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
+}
+
+/*
+* C2H event format:
+* Field TRIGGER CMD_LEN CONTENT CMD_SEQ CMD_ID
+* BITS [127:120] [119:112] [111:16] [15:8] [7:0]
+*/
+s32 c2h_evt_read_88xx(struct adapter *adapter, u8 *buf)
+{
+ s32 ret = _FAIL;
+ struct c2h_evt_hdr_88xx *c2h_evt;
+ int i;
+ u8 trigger;
+
+ if (!buf)
+ goto exit;
+
+ trigger = rtw_read8(adapter, REG_C2HEVT_CLEAR);
+
+ if (trigger == C2H_EVT_HOST_CLOSE)
+ goto exit; /* Not ready */
+ else if (trigger != C2H_EVT_FW_CLOSE)
+ goto clear_evt; /* Not a valid value */
+
+ c2h_evt = (struct c2h_evt_hdr_88xx *)buf;
+
+ memset(c2h_evt, 0, 16);
+
+ c2h_evt->id = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL);
+ c2h_evt->seq = rtw_read8(adapter, REG_C2HEVT_CMD_SEQ_88XX);
+ c2h_evt->plen = rtw_read8(adapter, REG_C2HEVT_CMD_LEN_88XX);
+
+ /* Read the content */
+ for (i = 0; i < c2h_evt->plen; i++)
+ c2h_evt->payload[i] = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL + 2 + i);
+
+ ret = _SUCCESS;
+
+clear_evt:
+ /*
+ * Clear event to notify FW we have read the command.
+ * If this field isn't clear, the FW won't update the next command message.
+ */
+ c2h_evt_clear(adapter);
+exit:
+ return ret;
+}
+
+u8 rtw_get_mgntframe_raid(struct adapter *adapter, unsigned char network_type)
+{
+ return (network_type & WIRELESS_11B) ? RATEID_IDX_B : RATEID_IDX_G;
+}
+
+void rtw_hal_update_sta_rate_mask(struct adapter *padapter, struct sta_info *psta)
+{
+ u8 i, limit;
+ u32 tx_ra_bitmap;
+
+ if (!psta)
+ return;
+
+ tx_ra_bitmap = 0;
+
+ /* b/g mode ra_bitmap */
+ for (i = 0; i < sizeof(psta->bssrateset); i++) {
+ if (psta->bssrateset[i])
+ tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i]&0x7f);
+ }
+
+ /* n mode ra_bitmap */
+ if (psta->htpriv.ht_option) {
+ limit = 8; /* 1R */
+
+ for (i = 0; i < limit; i++) {
+ if (psta->htpriv.ht_cap.mcs.rx_mask[i/8] & BIT(i%8))
+ tx_ra_bitmap |= BIT(i+12);
+ }
+ }
+
+ psta->ra_mask = tx_ra_bitmap;
+ psta->init_rate = get_highest_rate_idx(tx_ra_bitmap)&0x3f;
+}
+
+void hw_var_port_switch(struct adapter *adapter)
+{
+}
+
+void SetHwReg(struct adapter *adapter, u8 variable, u8 *val)
+{
+ struct hal_com_data *hal_data = GET_HAL_DATA(adapter);
+ struct dm_odm_t *odm = &(hal_data->odmpriv);
+
+ switch (variable) {
+ case HW_VAR_PORT_SWITCH:
+ hw_var_port_switch(adapter);
+ break;
+ case HW_VAR_INIT_RTS_RATE:
+ rtw_warn_on(1);
+ break;
+ case HW_VAR_SEC_CFG:
+ {
+ u16 reg_scr;
+
+ reg_scr = rtw_read16(adapter, REG_SECCFG);
+ rtw_write16(adapter, REG_SECCFG, reg_scr|SCR_CHK_KEYID|SCR_RxDecEnable|SCR_TxEncEnable);
+ }
+ break;
+ case HW_VAR_SEC_DK_CFG:
+ {
+ struct security_priv *sec = &adapter->securitypriv;
+ u8 reg_scr = rtw_read8(adapter, REG_SECCFG);
+
+ if (val) { /* Enable default key related setting */
+ reg_scr |= SCR_TXBCUSEDK;
+ if (sec->dot11AuthAlgrthm != dot11AuthAlgrthm_8021X)
+ reg_scr |= (SCR_RxUseDK|SCR_TxUseDK);
+ } else /* Disable default key related setting */
+ reg_scr &= ~(SCR_RXBCUSEDK|SCR_TXBCUSEDK|SCR_RxUseDK|SCR_TxUseDK);
+
+ rtw_write8(adapter, REG_SECCFG, reg_scr);
+ }
+ break;
+ case HW_VAR_DM_FLAG:
+ odm->SupportAbility = *((u32 *)val);
+ break;
+ case HW_VAR_DM_FUNC_OP:
+ if (*((u8 *)val) == true) {
+ /* save dm flag */
+ odm->BK_SupportAbility = odm->SupportAbility;
+ } else {
+ /* restore dm flag */
+ odm->SupportAbility = odm->BK_SupportAbility;
+ }
+ break;
+ case HW_VAR_DM_FUNC_SET:
+ if (*((u32 *)val) == DYNAMIC_ALL_FUNC_ENABLE) {
+ struct dm_priv *dm = &hal_data->dmpriv;
+ dm->DMFlag = dm->InitDMFlag;
+ odm->SupportAbility = dm->InitODMFlag;
+ } else {
+ odm->SupportAbility |= *((u32 *)val);
+ }
+ break;
+ case HW_VAR_DM_FUNC_CLR:
+ /*
+ * input is already a mask to clear function
+ * don't invert it again! George, Lucas@20130513
+ */
+ odm->SupportAbility &= *((u32 *)val);
+ break;
+ case HW_VAR_AMPDU_MIN_SPACE:
+ /* TODO - Is something needed here? */
+ break;
+ case HW_VAR_WIRELESS_MODE:
+ /* TODO - Is something needed here? */
+ break;
+ default:
+ netdev_dbg(adapter->pnetdev,
+ FUNC_ADPT_FMT " variable(%d) not defined!\n",
+ FUNC_ADPT_ARG(adapter), variable);
+ break;
+ }
+}
+
+void GetHwReg(struct adapter *adapter, u8 variable, u8 *val)
+{
+ struct hal_com_data *hal_data = GET_HAL_DATA(adapter);
+ struct dm_odm_t *odm = &(hal_data->odmpriv);
+
+ switch (variable) {
+ case HW_VAR_BASIC_RATE:
+ *((u16 *)val) = hal_data->BasicRateSet;
+ break;
+ case HW_VAR_DM_FLAG:
+ *((u32 *)val) = odm->SupportAbility;
+ break;
+ default:
+ netdev_dbg(adapter->pnetdev,
+ FUNC_ADPT_FMT " variable(%d) not defined!\n",
+ FUNC_ADPT_ARG(adapter), variable);
+ break;
+ }
+}
+
+
+
+
+u8 SetHalDefVar(
+ struct adapter *adapter, enum hal_def_variable variable, void *value
+)
+{
+ struct hal_com_data *hal_data = GET_HAL_DATA(adapter);
+ struct dm_odm_t *odm = &(hal_data->odmpriv);
+ u8 bResult = _SUCCESS;
+
+ switch (variable) {
+ case HAL_DEF_DBG_RX_INFO_DUMP:
+
+ if (odm->bLinked) {
+ #ifdef DBG_RX_SIGNAL_DISPLAY_RAW_DATA
+ rtw_dump_raw_rssi_info(adapter);
+ #endif
+ }
+ break;
+ case HW_DEF_ODM_DBG_FLAG:
+ ODM_CmnInfoUpdate(odm, ODM_CMNINFO_DBG_COMP, *((u64 *)value));
+ break;
+ case HW_DEF_ODM_DBG_LEVEL:
+ ODM_CmnInfoUpdate(odm, ODM_CMNINFO_DBG_LEVEL, *((u32 *)value));
+ break;
+ case HAL_DEF_DBG_DM_FUNC:
+ {
+ u8 dm_func = *((u8 *)value);
+ struct dm_priv *dm = &hal_data->dmpriv;
+
+ if (dm_func == 0) { /* disable all dynamic func */
+ odm->SupportAbility = DYNAMIC_FUNC_DISABLE;
+ } else if (dm_func == 1) {/* disable DIG */
+ odm->SupportAbility &= (~DYNAMIC_BB_DIG);
+ } else if (dm_func == 2) {/* disable High power */
+ odm->SupportAbility &= (~DYNAMIC_BB_DYNAMIC_TXPWR);
+ } else if (dm_func == 3) {/* disable tx power tracking */
+ odm->SupportAbility &= (~DYNAMIC_RF_CALIBRATION);
+ } else if (dm_func == 4) {/* disable BT coexistence */
+ dm->DMFlag &= (~DYNAMIC_FUNC_BT);
+ } else if (dm_func == 5) {/* disable antenna diversity */
+ odm->SupportAbility &= (~DYNAMIC_BB_ANT_DIV);
+ } else if (dm_func == 6) {/* turn on all dynamic func */
+ if (!(odm->SupportAbility & DYNAMIC_BB_DIG)) {
+ struct dig_t *pDigTable = &odm->DM_DigTable;
+ pDigTable->CurIGValue = rtw_read8(adapter, 0xc50);
+ }
+ dm->DMFlag |= DYNAMIC_FUNC_BT;
+ odm->SupportAbility = DYNAMIC_ALL_FUNC_ENABLE;
+ }
+ }
+ break;
+ case HAL_DEF_DBG_DUMP_RXPKT:
+ hal_data->bDumpRxPkt = *((u8 *)value);
+ break;
+ case HAL_DEF_DBG_DUMP_TXPKT:
+ hal_data->bDumpTxPkt = *((u8 *)value);
+ break;
+ case HAL_DEF_ANT_DETECT:
+ hal_data->AntDetection = *((u8 *)value);
+ break;
+ default:
+ netdev_dbg(adapter->pnetdev,
+ "%s: [WARNING] HAL_DEF_VARIABLE(%d) not defined!\n",
+ __func__, variable);
+ bResult = _FAIL;
+ break;
+ }
+
+ return bResult;
+}
+
+u8 GetHalDefVar(
+ struct adapter *adapter, enum hal_def_variable variable, void *value
+)
+{
+ struct hal_com_data *hal_data = GET_HAL_DATA(adapter);
+ u8 bResult = _SUCCESS;
+
+ switch (variable) {
+ case HAL_DEF_UNDERCORATEDSMOOTHEDPWDB:
+ {
+ struct mlme_priv *pmlmepriv;
+ struct sta_priv *pstapriv;
+ struct sta_info *psta;
+
+ pmlmepriv = &adapter->mlmepriv;
+ pstapriv = &adapter->stapriv;
+ psta = rtw_get_stainfo(pstapriv, pmlmepriv->cur_network.network.mac_address);
+ if (psta)
+ *((int *)value) = psta->rssi_stat.UndecoratedSmoothedPWDB;
+ }
+ break;
+ case HAL_DEF_DBG_DM_FUNC:
+ *((u32 *)value) = hal_data->odmpriv.SupportAbility;
+ break;
+ case HAL_DEF_DBG_DUMP_RXPKT:
+ *((u8 *)value) = hal_data->bDumpRxPkt;
+ break;
+ case HAL_DEF_DBG_DUMP_TXPKT:
+ *((u8 *)value) = hal_data->bDumpTxPkt;
+ break;
+ case HAL_DEF_ANT_DETECT:
+ *((u8 *)value) = hal_data->AntDetection;
+ break;
+ case HAL_DEF_MACID_SLEEP:
+ *(u8 *)value = false;
+ break;
+ case HAL_DEF_TX_PAGE_SIZE:
+ *((u32 *)value) = PAGE_SIZE_128;
+ break;
+ default:
+ netdev_dbg(adapter->pnetdev,
+ "%s: [WARNING] HAL_DEF_VARIABLE(%d) not defined!\n",
+ __func__, variable);
+ bResult = _FAIL;
+ break;
+ }
+
+ return bResult;
+}
+
+void GetHalODMVar(
+ struct adapter *Adapter,
+ enum hal_odm_variable eVariable,
+ void *pValue1,
+ void *pValue2
+)
+{
+ switch (eVariable) {
+ default:
+ break;
+ }
+}
+
+void SetHalODMVar(
+ struct adapter *Adapter,
+ enum hal_odm_variable eVariable,
+ void *pValue1,
+ bool bSet
+)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+ struct dm_odm_t *podmpriv = &pHalData->odmpriv;
+ /* _irqL irqL; */
+ switch (eVariable) {
+ case HAL_ODM_STA_INFO:
+ {
+ struct sta_info *psta = pValue1;
+ if (bSet) {
+ ODM_CmnInfoPtrArrayHook(podmpriv, ODM_CMNINFO_STA_STATUS, psta->mac_id, psta);
+ } else {
+ /* spin_lock_bh(&pHalData->odm_stainfo_lock); */
+ ODM_CmnInfoPtrArrayHook(podmpriv, ODM_CMNINFO_STA_STATUS, psta->mac_id, NULL);
+
+ /* spin_unlock_bh(&pHalData->odm_stainfo_lock); */
+ }
+ }
+ break;
+ case HAL_ODM_P2P_STATE:
+ ODM_CmnInfoUpdate(podmpriv, ODM_CMNINFO_WIFI_DIRECT, bSet);
+ break;
+ case HAL_ODM_WIFI_DISPLAY_STATE:
+ ODM_CmnInfoUpdate(podmpriv, ODM_CMNINFO_WIFI_DISPLAY, bSet);
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+bool eqNByte(u8 *str1, u8 *str2, u32 num)
+{
+ if (num == 0)
+ return false;
+ while (num > 0) {
+ num--;
+ if (str1[num] != str2[num])
+ return false;
+ }
+ return true;
+}
+
+/* */
+/* Description: */
+/* Translate a character to hex digit. */
+/* */
+u32 MapCharToHexDigit(char chTmp)
+{
+ if (chTmp >= '0' && chTmp <= '9')
+ return chTmp - '0';
+ else if (chTmp >= 'a' && chTmp <= 'f')
+ return 10 + (chTmp - 'a');
+ else if (chTmp >= 'A' && chTmp <= 'F')
+ return 10 + (chTmp - 'A');
+ else
+ return 0;
+}
+
+bool GetU1ByteIntegerFromStringInDecimal(char *Str, u8 *pInt)
+{
+ u16 i = 0;
+ *pInt = 0;
+
+ while (Str[i] != '\0') {
+ if (Str[i] >= '0' && Str[i] <= '9') {
+ *pInt *= 10;
+ *pInt += (Str[i] - '0');
+ } else
+ return false;
+
+ ++i;
+ }
+
+ return true;
+}
+
+/* <20121004, Kordan> For example,
+ * ParseQualifiedString(inString, 0, outString, '[', ']') gets "Kordan" from
+ * a string "Hello [Kordan]".
+ * If RightQualifier does not exist, it will hang in the while loop
+ */
+bool ParseQualifiedString(
+ char *In, u32 *Start, char *Out, char LeftQualifier, char RightQualifier
+)
+{
+ u32 i = 0, j = 0;
+ char c = In[(*Start)++];
+
+ if (c != LeftQualifier)
+ return false;
+
+ i = (*Start);
+ while ((c = In[(*Start)++]) != RightQualifier)
+ ; /* find ']' */
+ j = (*Start) - 2;
+ strncpy((char *)Out, (const char *)(In+i), j-i+1);
+
+ return true;
+}
+
+bool isAllSpaceOrTab(u8 *data, u8 size)
+{
+ u8 cnt = 0, NumOfSpaceAndTab = 0;
+
+ while (size > cnt) {
+ if (data[cnt] == ' ' || data[cnt] == '\t' || data[cnt] == '\0')
+ ++NumOfSpaceAndTab;
+
+ ++cnt;
+ }
+
+ return size == NumOfSpaceAndTab;
+}
+
+
+void rtw_hal_check_rxfifo_full(struct adapter *adapter)
+{
+ struct dvobj_priv *psdpriv = adapter->dvobj;
+ struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
+ int save_cnt = false;
+
+ /* switch counter to RX fifo */
+ /* printk("8723b or 8192e , MAC_667 set 0xf0\n"); */
+ rtw_write8(adapter, REG_RXERR_RPT+3, rtw_read8(adapter, REG_RXERR_RPT+3)|0xf0);
+ save_cnt = true;
+ /* todo: other chips */
+
+ if (save_cnt) {
+ /* rtw_write8(adapter, REG_RXERR_RPT+3, rtw_read8(adapter, REG_RXERR_RPT+3)|0xa0); */
+ pdbgpriv->dbg_rx_fifo_last_overflow = pdbgpriv->dbg_rx_fifo_curr_overflow;
+ pdbgpriv->dbg_rx_fifo_curr_overflow = rtw_read16(adapter, REG_RXERR_RPT);
+ pdbgpriv->dbg_rx_fifo_diff_overflow = pdbgpriv->dbg_rx_fifo_curr_overflow-pdbgpriv->dbg_rx_fifo_last_overflow;
+ }
+}
+
+void linked_info_dump(struct adapter *padapter, u8 benable)
+{
+ struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
+
+ if (padapter->bLinkInfoDump == benable)
+ return;
+
+ if (benable) {
+ pwrctrlpriv->org_power_mgnt = pwrctrlpriv->power_mgnt;/* keep org value */
+ rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
+
+ pwrctrlpriv->ips_org_mode = pwrctrlpriv->ips_mode;/* keep org value */
+ rtw_pm_set_ips(padapter, IPS_NONE);
+ } else {
+ rtw_pm_set_ips(padapter, pwrctrlpriv->ips_org_mode);
+
+ rtw_pm_set_lps(padapter, pwrctrlpriv->ips_org_mode);
+ }
+ padapter->bLinkInfoDump = benable;
+}
+
+#ifdef DBG_RX_SIGNAL_DISPLAY_RAW_DATA
+void rtw_get_raw_rssi_info(void *sel, struct adapter *padapter)
+{
+ u8 isCCKrate, rf_path;
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct rx_raw_rssi *psample_pkt_rssi = &padapter->recvpriv.raw_rssi_info;
+
+ netdev_dbg(padapter->pnetdev,
+ "RxRate = %s, PWDBALL = %d(%%), rx_pwr_all = %d(dBm)\n",
+ HDATA_RATE(psample_pkt_rssi->data_rate),
+ psample_pkt_rssi->pwdball, psample_pkt_rssi->pwr_all);
+
+ isCCKrate = psample_pkt_rssi->data_rate <= DESC_RATE11M;
+
+ if (isCCKrate)
+ psample_pkt_rssi->mimo_signal_strength[0] = psample_pkt_rssi->pwdball;
+
+ for (rf_path = 0; rf_path < pHalData->NumTotalRFPath; rf_path++) {
+ netdev_dbg(padapter->pnetdev,
+ "RF_PATH_%d =>signal_strength:%d(%%), signal_quality:%d(%%)\n",
+ rf_path,
+ psample_pkt_rssi->mimo_signal_strength[rf_path],
+ psample_pkt_rssi->mimo_signal_quality[rf_path]);
+
+ if (!isCCKrate) {
+ netdev_dbg(padapter->pnetdev,
+ "\trx_ofdm_pwr:%d(dBm), rx_ofdm_snr:%d(dB)\n",
+ psample_pkt_rssi->ofdm_pwr[rf_path],
+ psample_pkt_rssi->ofdm_snr[rf_path]);
+ }
+ }
+}
+
+void rtw_dump_raw_rssi_info(struct adapter *padapter)
+{
+ u8 isCCKrate, rf_path;
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct rx_raw_rssi *psample_pkt_rssi = &padapter->recvpriv.raw_rssi_info;
+
+ isCCKrate = psample_pkt_rssi->data_rate <= DESC_RATE11M;
+
+ if (isCCKrate)
+ psample_pkt_rssi->mimo_signal_strength[0] = psample_pkt_rssi->pwdball;
+
+ for (rf_path = 0; rf_path < pHalData->NumTotalRFPath; rf_path++) {
+ if (!isCCKrate) {
+ printk(", rx_ofdm_pwr:%d(dBm), rx_ofdm_snr:%d(dB)\n",
+ psample_pkt_rssi->ofdm_pwr[rf_path], psample_pkt_rssi->ofdm_snr[rf_path]);
+ } else {
+ printk("\n");
+ }
+ }
+}
+
+void rtw_store_phy_info(struct adapter *padapter, union recv_frame *prframe)
+{
+ u8 isCCKrate, rf_path;
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
+
+ struct odm_phy_info *pPhyInfo = (PODM_PHY_INFO_T)(&pattrib->phy_info);
+ struct rx_raw_rssi *psample_pkt_rssi = &padapter->recvpriv.raw_rssi_info;
+
+ psample_pkt_rssi->data_rate = pattrib->data_rate;
+ isCCKrate = pattrib->data_rate <= DESC_RATE11M;
+
+ psample_pkt_rssi->pwdball = pPhyInfo->rx_pwd_ba11;
+ psample_pkt_rssi->pwr_all = pPhyInfo->recv_signal_power;
+
+ for (rf_path = 0; rf_path < pHalData->NumTotalRFPath; rf_path++) {
+ psample_pkt_rssi->mimo_signal_strength[rf_path] = pPhyInfo->rx_mimo_signal_strength[rf_path];
+ psample_pkt_rssi->mimo_signal_quality[rf_path] = pPhyInfo->rx_mimo_signal_quality[rf_path];
+ if (!isCCKrate) {
+ psample_pkt_rssi->ofdm_pwr[rf_path] = pPhyInfo->RxPwr[rf_path];
+ psample_pkt_rssi->ofdm_snr[rf_path] = pPhyInfo->RxSNR[rf_path];
+ }
+ }
+}
+#endif
+
+static u32 Array_kfreemap[] = {
+ 0xf8, 0xe,
+ 0xf6, 0xc,
+ 0xf4, 0xa,
+ 0xf2, 0x8,
+ 0xf0, 0x6,
+ 0xf3, 0x4,
+ 0xf5, 0x2,
+ 0xf7, 0x0,
+ 0xf9, 0x0,
+ 0xfc, 0x0,
+};
+
+void rtw_bb_rf_gain_offset(struct adapter *padapter)
+{
+ u8 value = padapter->eeprompriv.EEPROMRFGainOffset;
+ u32 res, i = 0;
+ u32 *Array = Array_kfreemap;
+ u32 v1 = 0, v2 = 0, target = 0;
+
+ if (value & BIT4) {
+ if (padapter->eeprompriv.EEPROMRFGainVal != 0xff) {
+ res = rtw_hal_read_rfreg(padapter, RF_PATH_A, 0x7f, 0xffffffff);
+ res &= 0xfff87fff;
+ /* res &= 0xfff87fff; */
+ for (i = 0; i < ARRAY_SIZE(Array_kfreemap); i += 2) {
+ v1 = Array[i];
+ v2 = Array[i+1];
+ if (v1 == padapter->eeprompriv.EEPROMRFGainVal) {
+ target = v2;
+ break;
+ }
+ }
+ PHY_SetRFReg(padapter, RF_PATH_A, REG_RF_BB_GAIN_OFFSET, BIT18|BIT17|BIT16|BIT15, target);
+
+ /* res |= (padapter->eeprompriv.EEPROMRFGainVal & 0x0f)<< 15; */
+ /* rtw_hal_write_rfreg(padapter, RF_PATH_A, REG_RF_BB_GAIN_OFFSET, RF_GAIN_OFFSET_MASK, res); */
+ res = rtw_hal_read_rfreg(padapter, RF_PATH_A, 0x7f, 0xffffffff);
+ }
+ }
+}
diff --git a/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c b/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c
new file mode 100644
index 000000000..3e814a15e
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c
@@ -0,0 +1,984 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include <drv_types.h>
+#include <rtw_debug.h>
+#include <hal_data.h>
+#include <linux/kernel.h>
+
+u8 PHY_GetTxPowerByRateBase(struct adapter *Adapter, u8 RfPath,
+ enum rate_section RateSection)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+ u8 value = 0;
+
+ if (RfPath >= RF_PATH_MAX)
+ return 0;
+
+ switch (RateSection) {
+ case CCK:
+ value = pHalData->TxPwrByRateBase2_4G[RfPath][0];
+ break;
+ case OFDM:
+ value = pHalData->TxPwrByRateBase2_4G[RfPath][1];
+ break;
+ case HT_MCS0_MCS7:
+ value = pHalData->TxPwrByRateBase2_4G[RfPath][2];
+ break;
+ default:
+ break;
+ }
+
+ return value;
+}
+
+static void
+phy_SetTxPowerByRateBase(struct adapter *Adapter, u8 RfPath,
+ enum rate_section RateSection, u8 Value)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+
+ if (RfPath >= RF_PATH_MAX)
+ return;
+
+ switch (RateSection) {
+ case CCK:
+ pHalData->TxPwrByRateBase2_4G[RfPath][0] = Value;
+ break;
+ case OFDM:
+ pHalData->TxPwrByRateBase2_4G[RfPath][1] = Value;
+ break;
+ case HT_MCS0_MCS7:
+ pHalData->TxPwrByRateBase2_4G[RfPath][2] = Value;
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+phy_StoreTxPowerByRateBase(
+struct adapter *padapter
+ )
+{
+ u8 path, base;
+
+ for (path = RF_PATH_A; path <= RF_PATH_B; ++path) {
+ base = PHY_GetTxPowerByRate(padapter, path, MGN_11M);
+ phy_SetTxPowerByRateBase(padapter, path, CCK, base);
+
+ base = PHY_GetTxPowerByRate(padapter, path, MGN_54M);
+ phy_SetTxPowerByRateBase(padapter, path, OFDM, base);
+
+ base = PHY_GetTxPowerByRate(padapter, path, MGN_MCS7);
+ phy_SetTxPowerByRateBase(padapter, path, HT_MCS0_MCS7, base);
+ }
+}
+
+u8 PHY_GetRateSectionIndexOfTxPowerByRate(
+ struct adapter *padapter, u32 RegAddr, u32 BitMask
+)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
+ u8 index = 0;
+
+ if (pDM_Odm->PhyRegPgVersion == 0) {
+ switch (RegAddr) {
+ case rTxAGC_A_Rate18_06:
+ index = 0;
+ break;
+ case rTxAGC_A_Rate54_24:
+ index = 1;
+ break;
+ case rTxAGC_A_CCK1_Mcs32:
+ index = 6;
+ break;
+ case rTxAGC_B_CCK11_A_CCK2_11:
+ if (BitMask == bMaskH3Bytes)
+ index = 7;
+ else if (BitMask == 0x000000ff)
+ index = 15;
+ break;
+
+ case rTxAGC_A_Mcs03_Mcs00:
+ index = 2;
+ break;
+ case rTxAGC_A_Mcs07_Mcs04:
+ index = 3;
+ break;
+ case rTxAGC_B_Rate18_06:
+ index = 8;
+ break;
+ case rTxAGC_B_Rate54_24:
+ index = 9;
+ break;
+ case rTxAGC_B_CCK1_55_Mcs32:
+ index = 14;
+ break;
+ case rTxAGC_B_Mcs03_Mcs00:
+ index = 10;
+ break;
+ case rTxAGC_B_Mcs07_Mcs04:
+ index = 11;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return index;
+}
+
+void
+PHY_GetRateValuesOfTxPowerByRate(
+ struct adapter *padapter,
+ u32 RegAddr,
+ u32 BitMask,
+ u32 Value,
+ u8 *RateIndex,
+ s8 *PwrByRateVal,
+ u8 *RateNum
+)
+{
+ u8 i = 0;
+
+ switch (RegAddr) {
+ case rTxAGC_A_Rate18_06:
+ case rTxAGC_B_Rate18_06:
+ RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_6M);
+ RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_9M);
+ RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_12M);
+ RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(MGN_18M);
+ for (i = 0; i < 4; ++i) {
+ PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 +
+ ((Value >> (i * 8)) & 0xF));
+ }
+ *RateNum = 4;
+ break;
+
+ case rTxAGC_A_Rate54_24:
+ case rTxAGC_B_Rate54_24:
+ RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_24M);
+ RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_36M);
+ RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_48M);
+ RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(MGN_54M);
+ for (i = 0; i < 4; ++i) {
+ PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 +
+ ((Value >> (i * 8)) & 0xF));
+ }
+ *RateNum = 4;
+ break;
+
+ case rTxAGC_A_CCK1_Mcs32:
+ RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_1M);
+ PwrByRateVal[0] = (s8) ((((Value >> (8 + 4)) & 0xF)) * 10 +
+ ((Value >> 8) & 0xF));
+ *RateNum = 1;
+ break;
+
+ case rTxAGC_B_CCK11_A_CCK2_11:
+ if (BitMask == 0xffffff00) {
+ RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_2M);
+ RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_5_5M);
+ RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_11M);
+ for (i = 1; i < 4; ++i) {
+ PwrByRateVal[i - 1] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 +
+ ((Value >> (i * 8)) & 0xF));
+ }
+ *RateNum = 3;
+ } else if (BitMask == 0x000000ff) {
+ RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_11M);
+ PwrByRateVal[0] = (s8) ((((Value >> 4) & 0xF)) * 10 + (Value & 0xF));
+ *RateNum = 1;
+ }
+ break;
+
+ case rTxAGC_A_Mcs03_Mcs00:
+ case rTxAGC_B_Mcs03_Mcs00:
+ RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS0);
+ RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS1);
+ RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS2);
+ RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS3);
+ for (i = 0; i < 4; ++i) {
+ PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 +
+ ((Value >> (i * 8)) & 0xF));
+ }
+ *RateNum = 4;
+ break;
+
+ case rTxAGC_A_Mcs07_Mcs04:
+ case rTxAGC_B_Mcs07_Mcs04:
+ RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS4);
+ RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS5);
+ RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS6);
+ RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS7);
+ for (i = 0; i < 4; ++i) {
+ PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 +
+ ((Value >> (i * 8)) & 0xF));
+ }
+ *RateNum = 4;
+ break;
+
+ case rTxAGC_B_CCK1_55_Mcs32:
+ RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_1M);
+ RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_2M);
+ RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_5_5M);
+ for (i = 1; i < 4; ++i) {
+ PwrByRateVal[i - 1] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 +
+ ((Value >> (i * 8)) & 0xF));
+ }
+ *RateNum = 3;
+ break;
+
+ case 0xC20:
+ case 0xE20:
+ case 0x1820:
+ case 0x1a20:
+ RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_1M);
+ RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_2M);
+ RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_5_5M);
+ RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(MGN_11M);
+ for (i = 0; i < 4; ++i) {
+ PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 +
+ ((Value >> (i * 8)) & 0xF));
+ }
+ *RateNum = 4;
+ break;
+
+ case 0xC24:
+ case 0xE24:
+ case 0x1824:
+ case 0x1a24:
+ RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_6M);
+ RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_9M);
+ RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_12M);
+ RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(MGN_18M);
+ for (i = 0; i < 4; ++i) {
+ PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 +
+ ((Value >> (i * 8)) & 0xF));
+ }
+ *RateNum = 4;
+ break;
+
+ case 0xC28:
+ case 0xE28:
+ case 0x1828:
+ case 0x1a28:
+ RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_24M);
+ RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_36M);
+ RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_48M);
+ RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(MGN_54M);
+ for (i = 0; i < 4; ++i) {
+ PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 +
+ ((Value >> (i * 8)) & 0xF));
+ }
+ *RateNum = 4;
+ break;
+
+ case 0xC2C:
+ case 0xE2C:
+ case 0x182C:
+ case 0x1a2C:
+ RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS0);
+ RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS1);
+ RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS2);
+ RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS3);
+ for (i = 0; i < 4; ++i) {
+ PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 +
+ ((Value >> (i * 8)) & 0xF));
+ }
+ *RateNum = 4;
+ break;
+
+ case 0xC30:
+ case 0xE30:
+ case 0x1830:
+ case 0x1a30:
+ RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS4);
+ RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS5);
+ RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS6);
+ RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS7);
+ for (i = 0; i < 4; ++i) {
+ PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 +
+ ((Value >> (i * 8)) & 0xF));
+ }
+ *RateNum = 4;
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void PHY_StoreTxPowerByRateNew(struct adapter *padapter, u32 RfPath,
+ u32 RegAddr, u32 BitMask, u32 Data)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ u8 i = 0, rateIndex[4] = {0}, rateNum = 0;
+ s8 PwrByRateVal[4] = {0};
+
+ PHY_GetRateValuesOfTxPowerByRate(padapter, RegAddr, BitMask, Data, rateIndex, PwrByRateVal, &rateNum);
+
+ if (RfPath >= RF_PATH_MAX)
+ return;
+
+ for (i = 0; i < rateNum; ++i) {
+ pHalData->TxPwrByRateOffset[RfPath][rateIndex[i]] = PwrByRateVal[i];
+ }
+}
+
+static void PHY_StoreTxPowerByRateOld(
+ struct adapter *padapter, u32 RegAddr, u32 BitMask, u32 Data
+)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ u8 index = PHY_GetRateSectionIndexOfTxPowerByRate(padapter, RegAddr, BitMask);
+
+ pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][index] = Data;
+}
+
+void PHY_InitTxPowerByRate(struct adapter *padapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ u8 rfPath, rate;
+
+ for (rfPath = RF_PATH_A; rfPath < MAX_RF_PATH_NUM; ++rfPath)
+ for (rate = 0; rate < TX_PWR_BY_RATE_NUM_RATE; ++rate)
+ pHalData->TxPwrByRateOffset[rfPath][rate] = 0;
+}
+
+void PHY_StoreTxPowerByRate(
+ struct adapter *padapter,
+ u32 RfPath,
+ u32 RegAddr,
+ u32 BitMask,
+ u32 Data
+)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
+
+ if (pDM_Odm->PhyRegPgVersion > 0)
+ PHY_StoreTxPowerByRateNew(padapter, RfPath, RegAddr, BitMask, Data);
+ else if (pDM_Odm->PhyRegPgVersion == 0) {
+ PHY_StoreTxPowerByRateOld(padapter, RegAddr, BitMask, Data);
+ }
+}
+
+static void
+phy_ConvertTxPowerByRateInDbmToRelativeValues(
+struct adapter *padapter
+ )
+{
+ u8 base = 0, i = 0, value = 0, path = 0;
+ u8 cckRates[4] = {
+ MGN_1M, MGN_2M, MGN_5_5M, MGN_11M
+ };
+ u8 ofdmRates[8] = {
+ MGN_6M, MGN_9M, MGN_12M, MGN_18M, MGN_24M, MGN_36M, MGN_48M, MGN_54M
+ };
+ u8 mcs0_7Rates[8] = {
+ MGN_MCS0, MGN_MCS1, MGN_MCS2, MGN_MCS3, MGN_MCS4, MGN_MCS5, MGN_MCS6, MGN_MCS7
+ };
+ for (path = RF_PATH_A; path < RF_PATH_MAX; ++path) {
+ /* CCK */
+ base = PHY_GetTxPowerByRate(padapter, path, MGN_11M);
+ for (i = 0; i < ARRAY_SIZE(cckRates); ++i) {
+ value = PHY_GetTxPowerByRate(padapter, path, cckRates[i]);
+ PHY_SetTxPowerByRate(padapter, path, cckRates[i], value - base);
+ }
+
+ /* OFDM */
+ base = PHY_GetTxPowerByRate(padapter, path, MGN_54M);
+ for (i = 0; i < sizeof(ofdmRates); ++i) {
+ value = PHY_GetTxPowerByRate(padapter, path, ofdmRates[i]);
+ PHY_SetTxPowerByRate(padapter, path, ofdmRates[i], value - base);
+ }
+
+ /* HT MCS0~7 */
+ base = PHY_GetTxPowerByRate(padapter, path, MGN_MCS7);
+ for (i = 0; i < sizeof(mcs0_7Rates); ++i) {
+ value = PHY_GetTxPowerByRate(padapter, path, mcs0_7Rates[i]);
+ PHY_SetTxPowerByRate(padapter, path, mcs0_7Rates[i], value - base);
+ }
+ }
+}
+
+/*
+ * This function must be called if the value in the PHY_REG_PG.txt(or header)
+ * is exact dBm values
+ */
+void PHY_TxPowerByRateConfiguration(struct adapter *padapter)
+{
+ phy_StoreTxPowerByRateBase(padapter);
+ phy_ConvertTxPowerByRateInDbmToRelativeValues(padapter);
+}
+
+void PHY_SetTxPowerIndexByRateSection(
+ struct adapter *padapter, u8 RFPath, u8 Channel, u8 RateSection
+)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+
+ if (RateSection == CCK) {
+ u8 cckRates[] = {MGN_1M, MGN_2M, MGN_5_5M, MGN_11M};
+ PHY_SetTxPowerIndexByRateArray(padapter, RFPath,
+ pHalData->CurrentChannelBW,
+ Channel, cckRates,
+ ARRAY_SIZE(cckRates));
+
+ } else if (RateSection == OFDM) {
+ u8 ofdmRates[] = {MGN_6M, MGN_9M, MGN_12M, MGN_18M, MGN_24M, MGN_36M, MGN_48M, MGN_54M};
+ PHY_SetTxPowerIndexByRateArray(padapter, RFPath,
+ pHalData->CurrentChannelBW,
+ Channel, ofdmRates,
+ ARRAY_SIZE(ofdmRates));
+
+ } else if (RateSection == HT_MCS0_MCS7) {
+ u8 htRates1T[] = {MGN_MCS0, MGN_MCS1, MGN_MCS2, MGN_MCS3, MGN_MCS4, MGN_MCS5, MGN_MCS6, MGN_MCS7};
+ PHY_SetTxPowerIndexByRateArray(padapter, RFPath,
+ pHalData->CurrentChannelBW,
+ Channel, htRates1T,
+ ARRAY_SIZE(htRates1T));
+
+ }
+}
+
+u8 PHY_GetTxPowerIndexBase(
+ struct adapter *padapter,
+ u8 RFPath,
+ u8 Rate,
+ enum channel_width BandWidth,
+ u8 Channel
+)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ u8 txPower = 0;
+ u8 chnlIdx = (Channel-1);
+
+ if (HAL_IsLegalChannel(padapter, Channel) == false)
+ chnlIdx = 0;
+
+ if (IS_CCK_RATE(Rate))
+ txPower = pHalData->Index24G_CCK_Base[RFPath][chnlIdx];
+ else if (MGN_6M <= Rate)
+ txPower = pHalData->Index24G_BW40_Base[RFPath][chnlIdx];
+
+ /* OFDM-1T */
+ if ((MGN_6M <= Rate && Rate <= MGN_54M) && !IS_CCK_RATE(Rate))
+ txPower += pHalData->OFDM_24G_Diff[RFPath][TX_1S];
+
+ if (BandWidth == CHANNEL_WIDTH_20) { /* BW20-1S, BW20-2S */
+ if (MGN_MCS0 <= Rate && Rate <= MGN_MCS7)
+ txPower += pHalData->BW20_24G_Diff[RFPath][TX_1S];
+ } else if (BandWidth == CHANNEL_WIDTH_40) { /* BW40-1S, BW40-2S */
+ if (MGN_MCS0 <= Rate && Rate <= MGN_MCS7)
+ txPower += pHalData->BW40_24G_Diff[RFPath][TX_1S];
+ }
+
+ return txPower;
+}
+
+s8 PHY_GetTxPowerTrackingOffset(struct adapter *padapter, u8 RFPath, u8 Rate)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
+ s8 offset = 0;
+
+ if (pDM_Odm->RFCalibrateInfo.TxPowerTrackControl == false)
+ return offset;
+
+ if ((Rate == MGN_1M) || (Rate == MGN_2M) || (Rate == MGN_5_5M) || (Rate == MGN_11M))
+ offset = pDM_Odm->Remnant_CCKSwingIdx;
+ else
+ offset = pDM_Odm->Remnant_OFDMSwingIdx[RFPath];
+
+ return offset;
+}
+
+u8 PHY_GetRateIndexOfTxPowerByRate(u8 Rate)
+{
+ u8 index = 0;
+ switch (Rate) {
+ case MGN_1M:
+ index = 0;
+ break;
+ case MGN_2M:
+ index = 1;
+ break;
+ case MGN_5_5M:
+ index = 2;
+ break;
+ case MGN_11M:
+ index = 3;
+ break;
+ case MGN_6M:
+ index = 4;
+ break;
+ case MGN_9M:
+ index = 5;
+ break;
+ case MGN_12M:
+ index = 6;
+ break;
+ case MGN_18M:
+ index = 7;
+ break;
+ case MGN_24M:
+ index = 8;
+ break;
+ case MGN_36M:
+ index = 9;
+ break;
+ case MGN_48M:
+ index = 10;
+ break;
+ case MGN_54M:
+ index = 11;
+ break;
+ case MGN_MCS0:
+ index = 12;
+ break;
+ case MGN_MCS1:
+ index = 13;
+ break;
+ case MGN_MCS2:
+ index = 14;
+ break;
+ case MGN_MCS3:
+ index = 15;
+ break;
+ case MGN_MCS4:
+ index = 16;
+ break;
+ case MGN_MCS5:
+ index = 17;
+ break;
+ case MGN_MCS6:
+ index = 18;
+ break;
+ case MGN_MCS7:
+ index = 19;
+ break;
+ default:
+ break;
+ }
+ return index;
+}
+
+s8 PHY_GetTxPowerByRate(struct adapter *padapter, u8 RFPath, u8 Rate)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ s8 value = 0;
+ u8 rateIndex = PHY_GetRateIndexOfTxPowerByRate(Rate);
+
+ if ((padapter->registrypriv.RegEnableTxPowerByRate == 2 && pHalData->EEPROMRegulatory == 2) ||
+ padapter->registrypriv.RegEnableTxPowerByRate == 0)
+ return 0;
+
+ if (RFPath >= RF_PATH_MAX)
+ return value;
+
+ if (rateIndex >= TX_PWR_BY_RATE_NUM_RATE)
+ return value;
+
+ return pHalData->TxPwrByRateOffset[RFPath][rateIndex];
+
+}
+
+void PHY_SetTxPowerByRate(
+ struct adapter *padapter,
+ u8 RFPath,
+ u8 Rate,
+ s8 Value
+)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ u8 rateIndex = PHY_GetRateIndexOfTxPowerByRate(Rate);
+
+ if (RFPath >= RF_PATH_MAX)
+ return;
+
+ if (rateIndex >= TX_PWR_BY_RATE_NUM_RATE)
+ return;
+
+ pHalData->TxPwrByRateOffset[RFPath][rateIndex] = Value;
+}
+
+void PHY_SetTxPowerLevelByPath(struct adapter *Adapter, u8 channel, u8 path)
+{
+ PHY_SetTxPowerIndexByRateSection(Adapter, path, channel, CCK);
+
+ PHY_SetTxPowerIndexByRateSection(Adapter, path, channel, OFDM);
+ PHY_SetTxPowerIndexByRateSection(Adapter, path, channel, HT_MCS0_MCS7);
+}
+
+void PHY_SetTxPowerIndexByRateArray(
+ struct adapter *padapter,
+ u8 RFPath,
+ enum channel_width BandWidth,
+ u8 Channel,
+ u8 *Rates,
+ u8 RateArraySize
+)
+{
+ u32 powerIndex = 0;
+ int i = 0;
+
+ for (i = 0; i < RateArraySize; ++i) {
+ powerIndex = PHY_GetTxPowerIndex(padapter, RFPath, Rates[i], BandWidth, Channel);
+ PHY_SetTxPowerIndex(padapter, powerIndex, RFPath, Rates[i]);
+ }
+}
+
+static s8 phy_GetWorldWideLimit(s8 *LimitTable)
+{
+ s8 min = LimitTable[0];
+ u8 i = 0;
+
+ for (i = 0; i < MAX_REGULATION_NUM; ++i) {
+ if (LimitTable[i] < min)
+ min = LimitTable[i];
+ }
+
+ return min;
+}
+
+static s8 phy_GetChannelIndexOfTxPowerLimit(u8 Channel)
+{
+ return Channel - 1;
+}
+
+static s16 get_bandwidth_idx(const enum channel_width bandwidth)
+{
+ switch (bandwidth) {
+ case CHANNEL_WIDTH_20:
+ return 0;
+ case CHANNEL_WIDTH_40:
+ return 1;
+ default:
+ return -1;
+ }
+}
+
+static s16 get_rate_sctn_idx(const u8 rate)
+{
+ switch (rate) {
+ case MGN_1M: case MGN_2M: case MGN_5_5M: case MGN_11M:
+ return 0;
+ case MGN_6M: case MGN_9M: case MGN_12M: case MGN_18M:
+ case MGN_24M: case MGN_36M: case MGN_48M: case MGN_54M:
+ return 1;
+ case MGN_MCS0: case MGN_MCS1: case MGN_MCS2: case MGN_MCS3:
+ case MGN_MCS4: case MGN_MCS5: case MGN_MCS6: case MGN_MCS7:
+ return 2;
+ default:
+ return -1;
+ }
+}
+
+s8 phy_get_tx_pwr_lmt(struct adapter *adapter, u32 reg_pwr_tbl_sel,
+ enum channel_width bandwidth,
+ u8 rf_path, u8 data_rate, u8 channel)
+{
+ s16 idx_regulation = -1;
+ s16 idx_bandwidth = -1;
+ s16 idx_rate_sctn = -1;
+ s16 idx_channel = -1;
+ s8 pwr_lmt = MAX_POWER_INDEX;
+ struct hal_com_data *hal_data = GET_HAL_DATA(adapter);
+ s8 limits[10] = {0}; u8 i = 0;
+
+ if (((adapter->registrypriv.RegEnableTxPowerLimit == 2) &&
+ (hal_data->EEPROMRegulatory != 1)) ||
+ (adapter->registrypriv.RegEnableTxPowerLimit == 0))
+ return MAX_POWER_INDEX;
+
+ switch (adapter->registrypriv.RegPwrTblSel) {
+ case 1:
+ idx_regulation = TXPWR_LMT_ETSI;
+ break;
+ case 2:
+ idx_regulation = TXPWR_LMT_MKK;
+ break;
+ case 3:
+ idx_regulation = TXPWR_LMT_FCC;
+ break;
+ case 4:
+ idx_regulation = TXPWR_LMT_WW;
+ break;
+ default:
+ idx_regulation = hal_data->Regulation2_4G;
+ break;
+ }
+
+ idx_bandwidth = get_bandwidth_idx(bandwidth);
+ idx_rate_sctn = get_rate_sctn_idx(data_rate);
+
+ /* workaround for wrong index combination to obtain tx power limit, */
+ /* OFDM only exists in BW 20M */
+ /* CCK table will only be given in BW 20M */
+ /* HT on 80M will reference to HT on 40M */
+ if (idx_rate_sctn == 0 || idx_rate_sctn == 1)
+ idx_bandwidth = 0;
+
+ channel = phy_GetChannelIndexOfTxPowerLimit(channel);
+
+ if (idx_regulation == -1 || idx_bandwidth == -1 ||
+ idx_rate_sctn == -1 || idx_channel == -1)
+ return MAX_POWER_INDEX;
+
+
+ for (i = 0; i < MAX_REGULATION_NUM; i++)
+ limits[i] = hal_data->TxPwrLimit_2_4G[i]
+ [idx_bandwidth]
+ [idx_rate_sctn]
+ [idx_channel]
+ [rf_path];
+
+ pwr_lmt = (idx_regulation == TXPWR_LMT_WW) ?
+ phy_GetWorldWideLimit(limits) :
+ hal_data->TxPwrLimit_2_4G[idx_regulation]
+ [idx_bandwidth]
+ [idx_rate_sctn]
+ [idx_channel]
+ [rf_path];
+
+ return pwr_lmt;
+}
+
+void PHY_ConvertTxPowerLimitToPowerIndex(struct adapter *Adapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+ u8 BW40PwrBasedBm2_4G = 0x2E;
+ u8 regulation, bw, channel, rateSection;
+ s8 tempValue = 0, tempPwrLmt = 0;
+ u8 rfPath = 0;
+
+ for (regulation = 0; regulation < MAX_REGULATION_NUM; ++regulation) {
+ for (bw = 0; bw < MAX_2_4G_BANDWIDTH_NUM; ++bw) {
+ for (channel = 0; channel < CHANNEL_MAX_NUMBER_2G; ++channel) {
+ for (rateSection = 0; rateSection < MAX_RATE_SECTION_NUM; ++rateSection) {
+ tempPwrLmt = pHalData->TxPwrLimit_2_4G[regulation][bw][rateSection][channel][RF_PATH_A];
+
+ for (rfPath = RF_PATH_A; rfPath < MAX_RF_PATH_NUM; ++rfPath) {
+ if (pHalData->odmpriv.PhyRegPgValueType == PHY_REG_PG_EXACT_VALUE) {
+ if (rateSection == 2) /* HT 1T */
+ BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, rfPath, HT_MCS0_MCS7);
+ else if (rateSection == 1) /* OFDM */
+ BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, rfPath, OFDM);
+ else if (rateSection == 0) /* CCK */
+ BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, rfPath, CCK);
+ } else
+ BW40PwrBasedBm2_4G = Adapter->registrypriv.RegPowerBase * 2;
+
+ if (tempPwrLmt != MAX_POWER_INDEX) {
+ tempValue = tempPwrLmt - BW40PwrBasedBm2_4G;
+ pHalData->TxPwrLimit_2_4G[regulation][bw][rateSection][channel][rfPath] = tempValue;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void PHY_InitTxPowerLimit(struct adapter *Adapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+ u8 i, j, k, l, m;
+
+ for (i = 0; i < MAX_REGULATION_NUM; ++i) {
+ for (j = 0; j < MAX_2_4G_BANDWIDTH_NUM; ++j)
+ for (k = 0; k < MAX_RATE_SECTION_NUM; ++k)
+ for (m = 0; m < CHANNEL_MAX_NUMBER_2G; ++m)
+ for (l = 0; l < MAX_RF_PATH_NUM; ++l)
+ pHalData->TxPwrLimit_2_4G[i][j][k][m][l] = MAX_POWER_INDEX;
+ }
+}
+
+void PHY_SetTxPowerLimit(
+ struct adapter *Adapter,
+ u8 *Regulation,
+ u8 *Bandwidth,
+ u8 *RateSection,
+ u8 *RfPath,
+ u8 *Channel,
+ u8 *PowerLimit
+)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+ u8 regulation = 0, bandwidth = 0, rateSection = 0, channel;
+ s8 powerLimit = 0, prevPowerLimit, channelIndex;
+
+ GetU1ByteIntegerFromStringInDecimal((s8 *)Channel, &channel);
+ GetU1ByteIntegerFromStringInDecimal((s8 *)PowerLimit, &powerLimit);
+
+ powerLimit = powerLimit > MAX_POWER_INDEX ? MAX_POWER_INDEX : powerLimit;
+
+ if (eqNByte(Regulation, (u8 *)("FCC"), 3))
+ regulation = 0;
+ else if (eqNByte(Regulation, (u8 *)("MKK"), 3))
+ regulation = 1;
+ else if (eqNByte(Regulation, (u8 *)("ETSI"), 4))
+ regulation = 2;
+ else if (eqNByte(Regulation, (u8 *)("WW13"), 4))
+ regulation = 3;
+
+ if (eqNByte(RateSection, (u8 *)("CCK"), 3) && eqNByte(RfPath, (u8 *)("1T"), 2))
+ rateSection = 0;
+ else if (eqNByte(RateSection, (u8 *)("OFDM"), 4) && eqNByte(RfPath, (u8 *)("1T"), 2))
+ rateSection = 1;
+ else if (eqNByte(RateSection, (u8 *)("HT"), 2) && eqNByte(RfPath, (u8 *)("1T"), 2))
+ rateSection = 2;
+ else
+ return;
+
+ if (eqNByte(Bandwidth, (u8 *)("20M"), 3))
+ bandwidth = 0;
+ else if (eqNByte(Bandwidth, (u8 *)("40M"), 3))
+ bandwidth = 1;
+
+ channelIndex = phy_GetChannelIndexOfTxPowerLimit(channel);
+
+ if (channelIndex == -1)
+ return;
+
+ prevPowerLimit = pHalData->TxPwrLimit_2_4G[regulation][bandwidth][rateSection][channelIndex][RF_PATH_A];
+
+ if (powerLimit < prevPowerLimit)
+ pHalData->TxPwrLimit_2_4G[regulation][bandwidth][rateSection][channelIndex][RF_PATH_A] = powerLimit;
+}
+
+void Hal_ChannelPlanToRegulation(struct adapter *Adapter, u16 ChannelPlan)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+ pHalData->Regulation2_4G = TXPWR_LMT_WW;
+
+ switch (ChannelPlan) {
+ case RT_CHANNEL_DOMAIN_WORLD_NULL:
+ pHalData->Regulation2_4G = TXPWR_LMT_WW;
+ break;
+ case RT_CHANNEL_DOMAIN_ETSI1_NULL:
+ pHalData->Regulation2_4G = TXPWR_LMT_ETSI;
+ break;
+ case RT_CHANNEL_DOMAIN_FCC1_NULL:
+ pHalData->Regulation2_4G = TXPWR_LMT_FCC;
+ break;
+ case RT_CHANNEL_DOMAIN_MKK1_NULL:
+ pHalData->Regulation2_4G = TXPWR_LMT_MKK;
+ break;
+ case RT_CHANNEL_DOMAIN_ETSI2_NULL:
+ pHalData->Regulation2_4G = TXPWR_LMT_ETSI;
+ break;
+ case RT_CHANNEL_DOMAIN_FCC1_FCC1:
+ pHalData->Regulation2_4G = TXPWR_LMT_FCC;
+ break;
+ case RT_CHANNEL_DOMAIN_WORLD_ETSI1:
+ pHalData->Regulation2_4G = TXPWR_LMT_FCC;
+ break;
+ case RT_CHANNEL_DOMAIN_MKK1_MKK1:
+ pHalData->Regulation2_4G = TXPWR_LMT_MKK;
+ break;
+ case RT_CHANNEL_DOMAIN_WORLD_KCC1:
+ pHalData->Regulation2_4G = TXPWR_LMT_FCC;
+ break;
+ case RT_CHANNEL_DOMAIN_WORLD_FCC2:
+ pHalData->Regulation2_4G = TXPWR_LMT_FCC;
+ break;
+ case RT_CHANNEL_DOMAIN_WORLD_FCC3:
+ pHalData->Regulation2_4G = TXPWR_LMT_FCC;
+ break;
+ case RT_CHANNEL_DOMAIN_WORLD_FCC4:
+ pHalData->Regulation2_4G = TXPWR_LMT_FCC;
+ break;
+ case RT_CHANNEL_DOMAIN_WORLD_FCC5:
+ pHalData->Regulation2_4G = TXPWR_LMT_FCC;
+ break;
+ case RT_CHANNEL_DOMAIN_WORLD_FCC6:
+ pHalData->Regulation2_4G = TXPWR_LMT_FCC;
+ break;
+ case RT_CHANNEL_DOMAIN_FCC1_FCC7:
+ pHalData->Regulation2_4G = TXPWR_LMT_FCC;
+ break;
+ case RT_CHANNEL_DOMAIN_WORLD_ETSI2:
+ pHalData->Regulation2_4G = TXPWR_LMT_FCC;
+ break;
+ case RT_CHANNEL_DOMAIN_WORLD_ETSI3:
+ pHalData->Regulation2_4G = TXPWR_LMT_FCC;
+ break;
+ case RT_CHANNEL_DOMAIN_MKK1_MKK2:
+ pHalData->Regulation2_4G = TXPWR_LMT_MKK;
+ break;
+ case RT_CHANNEL_DOMAIN_MKK1_MKK3:
+ pHalData->Regulation2_4G = TXPWR_LMT_MKK;
+ break;
+ case RT_CHANNEL_DOMAIN_FCC1_NCC1:
+ pHalData->Regulation2_4G = TXPWR_LMT_FCC;
+ break;
+ case RT_CHANNEL_DOMAIN_FCC1_NCC2:
+ pHalData->Regulation2_4G = TXPWR_LMT_FCC;
+ break;
+ case RT_CHANNEL_DOMAIN_GLOBAL_NULL:
+ pHalData->Regulation2_4G = TXPWR_LMT_WW;
+ break;
+ case RT_CHANNEL_DOMAIN_ETSI1_ETSI4:
+ pHalData->Regulation2_4G = TXPWR_LMT_ETSI;
+ break;
+ case RT_CHANNEL_DOMAIN_FCC1_FCC2:
+ pHalData->Regulation2_4G = TXPWR_LMT_FCC;
+ break;
+ case RT_CHANNEL_DOMAIN_FCC1_NCC3:
+ pHalData->Regulation2_4G = TXPWR_LMT_FCC;
+ break;
+ case RT_CHANNEL_DOMAIN_WORLD_ETSI5:
+ pHalData->Regulation2_4G = TXPWR_LMT_ETSI;
+ break;
+ case RT_CHANNEL_DOMAIN_FCC1_FCC8:
+ pHalData->Regulation2_4G = TXPWR_LMT_FCC;
+ break;
+ case RT_CHANNEL_DOMAIN_WORLD_ETSI6:
+ pHalData->Regulation2_4G = TXPWR_LMT_ETSI;
+ break;
+ case RT_CHANNEL_DOMAIN_WORLD_ETSI7:
+ pHalData->Regulation2_4G = TXPWR_LMT_ETSI;
+ break;
+ case RT_CHANNEL_DOMAIN_WORLD_ETSI8:
+ pHalData->Regulation2_4G = TXPWR_LMT_ETSI;
+ break;
+ case RT_CHANNEL_DOMAIN_WORLD_ETSI9:
+ pHalData->Regulation2_4G = TXPWR_LMT_ETSI;
+ break;
+ case RT_CHANNEL_DOMAIN_WORLD_ETSI10:
+ pHalData->Regulation2_4G = TXPWR_LMT_ETSI;
+ break;
+ case RT_CHANNEL_DOMAIN_WORLD_ETSI11:
+ pHalData->Regulation2_4G = TXPWR_LMT_ETSI;
+ break;
+ case RT_CHANNEL_DOMAIN_FCC1_NCC4:
+ pHalData->Regulation2_4G = TXPWR_LMT_FCC;
+ break;
+ case RT_CHANNEL_DOMAIN_WORLD_ETSI12:
+ pHalData->Regulation2_4G = TXPWR_LMT_ETSI;
+ break;
+ case RT_CHANNEL_DOMAIN_FCC1_FCC9:
+ pHalData->Regulation2_4G = TXPWR_LMT_FCC;
+ break;
+ case RT_CHANNEL_DOMAIN_WORLD_ETSI13:
+ pHalData->Regulation2_4G = TXPWR_LMT_ETSI;
+ break;
+ case RT_CHANNEL_DOMAIN_FCC1_FCC10:
+ pHalData->Regulation2_4G = TXPWR_LMT_FCC;
+ break;
+ case RT_CHANNEL_DOMAIN_REALTEK_DEFINE: /* Realtek Reserve */
+ pHalData->Regulation2_4G = TXPWR_LMT_WW;
+ break;
+ default:
+ break;
+ }
+}
diff --git a/drivers/staging/rtl8723bs/hal/hal_intf.c b/drivers/staging/rtl8723bs/hal/hal_intf.c
new file mode 100644
index 000000000..6bb0ff8d7
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/hal_intf.c
@@ -0,0 +1,439 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#include <drv_types.h>
+#include <rtw_debug.h>
+#include <hal_data.h>
+
+void rtw_hal_chip_configure(struct adapter *padapter)
+{
+ if (padapter->HalFunc.intf_chip_configure)
+ padapter->HalFunc.intf_chip_configure(padapter);
+}
+
+void rtw_hal_read_chip_info(struct adapter *padapter)
+{
+ if (padapter->HalFunc.read_adapter_info)
+ padapter->HalFunc.read_adapter_info(padapter);
+}
+
+void rtw_hal_read_chip_version(struct adapter *padapter)
+{
+ if (padapter->HalFunc.read_chip_version)
+ padapter->HalFunc.read_chip_version(padapter);
+}
+
+void rtw_hal_def_value_init(struct adapter *padapter)
+{
+ if (is_primary_adapter(padapter))
+ if (padapter->HalFunc.init_default_value)
+ padapter->HalFunc.init_default_value(padapter);
+}
+
+void rtw_hal_free_data(struct adapter *padapter)
+{
+ /* free HAL Data */
+ rtw_hal_data_deinit(padapter);
+
+ if (is_primary_adapter(padapter))
+ if (padapter->HalFunc.free_hal_data)
+ padapter->HalFunc.free_hal_data(padapter);
+}
+
+void rtw_hal_dm_init(struct adapter *padapter)
+{
+ if (is_primary_adapter(padapter))
+ if (padapter->HalFunc.dm_init)
+ padapter->HalFunc.dm_init(padapter);
+}
+
+void rtw_hal_dm_deinit(struct adapter *padapter)
+{
+ /* cancel dm timer */
+ if (is_primary_adapter(padapter))
+ if (padapter->HalFunc.dm_deinit)
+ padapter->HalFunc.dm_deinit(padapter);
+}
+
+static void rtw_hal_init_opmode(struct adapter *padapter)
+{
+ enum ndis_802_11_network_infrastructure networkType = Ndis802_11InfrastructureMax;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ signed int fw_state;
+
+ fw_state = get_fwstate(pmlmepriv);
+
+ if (fw_state & WIFI_ADHOC_STATE)
+ networkType = Ndis802_11IBSS;
+ else if (fw_state & WIFI_STATION_STATE)
+ networkType = Ndis802_11Infrastructure;
+ else if (fw_state & WIFI_AP_STATE)
+ networkType = Ndis802_11APMode;
+ else
+ return;
+
+ rtw_setopmode_cmd(padapter, networkType, false);
+}
+
+uint rtw_hal_init(struct adapter *padapter)
+{
+ uint status;
+ struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+
+ status = padapter->HalFunc.hal_init(padapter);
+
+ if (status == _SUCCESS) {
+ rtw_hal_init_opmode(padapter);
+
+ dvobj->padapters->hw_init_completed = true;
+
+ if (padapter->registrypriv.notch_filter == 1)
+ rtw_hal_notch_filter(padapter, 1);
+
+ rtw_hal_reset_security_engine(padapter);
+
+ rtw_sec_restore_wep_key(dvobj->padapters);
+
+ init_hw_mlme_ext(padapter);
+
+ rtw_bb_rf_gain_offset(padapter);
+ } else {
+ dvobj->padapters->hw_init_completed = false;
+ }
+
+ return status;
+}
+
+uint rtw_hal_deinit(struct adapter *padapter)
+{
+ uint status = _SUCCESS;
+ struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+
+ status = padapter->HalFunc.hal_deinit(padapter);
+
+ if (status == _SUCCESS) {
+ padapter = dvobj->padapters;
+ padapter->hw_init_completed = false;
+ }
+
+ return status;
+}
+
+void rtw_hal_set_hwreg(struct adapter *padapter, u8 variable, u8 *val)
+{
+ if (padapter->HalFunc.SetHwRegHandler)
+ padapter->HalFunc.SetHwRegHandler(padapter, variable, val);
+}
+
+void rtw_hal_get_hwreg(struct adapter *padapter, u8 variable, u8 *val)
+{
+ if (padapter->HalFunc.GetHwRegHandler)
+ padapter->HalFunc.GetHwRegHandler(padapter, variable, val);
+}
+
+void rtw_hal_set_hwreg_with_buf(struct adapter *padapter, u8 variable, u8 *pbuf, int len)
+{
+ if (padapter->HalFunc.SetHwRegHandlerWithBuf)
+ padapter->HalFunc.SetHwRegHandlerWithBuf(padapter, variable, pbuf, len);
+}
+
+u8 rtw_hal_set_def_var(struct adapter *padapter, enum hal_def_variable eVariable, void *pValue)
+{
+ if (padapter->HalFunc.SetHalDefVarHandler)
+ return padapter->HalFunc.SetHalDefVarHandler(padapter, eVariable, pValue);
+ return _FAIL;
+}
+
+u8 rtw_hal_get_def_var(struct adapter *padapter, enum hal_def_variable eVariable, void *pValue)
+{
+ if (padapter->HalFunc.GetHalDefVarHandler)
+ return padapter->HalFunc.GetHalDefVarHandler(padapter, eVariable, pValue);
+ return _FAIL;
+}
+
+void rtw_hal_set_odm_var(struct adapter *padapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet)
+{
+ if (padapter->HalFunc.SetHalODMVarHandler)
+ padapter->HalFunc.SetHalODMVarHandler(padapter, eVariable, pValue1, bSet);
+}
+
+void rtw_hal_get_odm_var(struct adapter *padapter, enum hal_odm_variable eVariable, void *pValue1, void *pValue2)
+{
+ if (padapter->HalFunc.GetHalODMVarHandler)
+ padapter->HalFunc.GetHalODMVarHandler(padapter, eVariable, pValue1, pValue2);
+}
+
+void rtw_hal_enable_interrupt(struct adapter *padapter)
+{
+ if (padapter->HalFunc.enable_interrupt)
+ padapter->HalFunc.enable_interrupt(padapter);
+}
+
+void rtw_hal_disable_interrupt(struct adapter *padapter)
+{
+ if (padapter->HalFunc.disable_interrupt)
+ padapter->HalFunc.disable_interrupt(padapter);
+}
+
+u8 rtw_hal_check_ips_status(struct adapter *padapter)
+{
+ u8 val = false;
+
+ if (padapter->HalFunc.check_ips_status)
+ val = padapter->HalFunc.check_ips_status(padapter);
+
+ return val;
+}
+
+s32 rtw_hal_xmitframe_enqueue(struct adapter *padapter, struct xmit_frame *pxmitframe)
+{
+ if (padapter->HalFunc.hal_xmitframe_enqueue)
+ return padapter->HalFunc.hal_xmitframe_enqueue(padapter, pxmitframe);
+
+ return false;
+}
+
+s32 rtw_hal_xmit(struct adapter *padapter, struct xmit_frame *pxmitframe)
+{
+ if (padapter->HalFunc.hal_xmit)
+ return padapter->HalFunc.hal_xmit(padapter, pxmitframe);
+
+ return false;
+}
+
+/*
+ * [IMPORTANT] This function would be run in interrupt context.
+ */
+s32 rtw_hal_mgnt_xmit(struct adapter *padapter, struct xmit_frame *pmgntframe)
+{
+ s32 ret = _FAIL;
+
+ update_mgntframe_attrib_addr(padapter, pmgntframe);
+ /* pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; */
+ /* pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; */
+ /* memcpy(pmgntframe->attrib.ra, pwlanhdr->addr1, ETH_ALEN); */
+
+ if (padapter->securitypriv.binstallBIPkey == true) {
+ if (IS_MCAST(pmgntframe->attrib.ra)) {
+ pmgntframe->attrib.encrypt = _BIP_;
+ /* pmgntframe->attrib.bswenc = true; */
+ } else {
+ pmgntframe->attrib.encrypt = _AES_;
+ pmgntframe->attrib.bswenc = true;
+ }
+ rtw_mgmt_xmitframe_coalesce(padapter, pmgntframe->pkt, pmgntframe);
+ }
+
+ if (padapter->HalFunc.mgnt_xmit)
+ ret = padapter->HalFunc.mgnt_xmit(padapter, pmgntframe);
+ return ret;
+}
+
+s32 rtw_hal_init_xmit_priv(struct adapter *padapter)
+{
+ if (padapter->HalFunc.init_xmit_priv)
+ return padapter->HalFunc.init_xmit_priv(padapter);
+ return _FAIL;
+}
+
+void rtw_hal_free_xmit_priv(struct adapter *padapter)
+{
+ if (padapter->HalFunc.free_xmit_priv)
+ padapter->HalFunc.free_xmit_priv(padapter);
+}
+
+s32 rtw_hal_init_recv_priv(struct adapter *padapter)
+{
+ if (padapter->HalFunc.init_recv_priv)
+ return padapter->HalFunc.init_recv_priv(padapter);
+
+ return _FAIL;
+}
+
+void rtw_hal_free_recv_priv(struct adapter *padapter)
+{
+ if (padapter->HalFunc.free_recv_priv)
+ padapter->HalFunc.free_recv_priv(padapter);
+}
+
+void rtw_hal_update_ra_mask(struct sta_info *psta, u8 rssi_level)
+{
+ struct adapter *padapter;
+ struct mlme_priv *pmlmepriv;
+
+ if (!psta)
+ return;
+
+ padapter = psta->padapter;
+
+ pmlmepriv = &(padapter->mlmepriv);
+
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
+ add_RATid(padapter, psta, rssi_level);
+ else {
+ if (padapter->HalFunc.UpdateRAMaskHandler)
+ padapter->HalFunc.UpdateRAMaskHandler(padapter, psta->mac_id, rssi_level);
+ }
+}
+
+void rtw_hal_add_ra_tid(struct adapter *padapter, u32 bitmap, u8 *arg, u8 rssi_level)
+{
+ if (padapter->HalFunc.Add_RateATid)
+ padapter->HalFunc.Add_RateATid(padapter, bitmap, arg, rssi_level);
+}
+
+/*Start specifical interface thread */
+void rtw_hal_start_thread(struct adapter *padapter)
+{
+ if (padapter->HalFunc.run_thread)
+ padapter->HalFunc.run_thread(padapter);
+}
+/*Start specifical interface thread */
+void rtw_hal_stop_thread(struct adapter *padapter)
+{
+ if (padapter->HalFunc.cancel_thread)
+ padapter->HalFunc.cancel_thread(padapter);
+}
+
+u32 rtw_hal_read_bbreg(struct adapter *padapter, u32 RegAddr, u32 BitMask)
+{
+ u32 data = 0;
+
+ if (padapter->HalFunc.read_bbreg)
+ data = padapter->HalFunc.read_bbreg(padapter, RegAddr, BitMask);
+ return data;
+}
+void rtw_hal_write_bbreg(struct adapter *padapter, u32 RegAddr, u32 BitMask, u32 Data)
+{
+ if (padapter->HalFunc.write_bbreg)
+ padapter->HalFunc.write_bbreg(padapter, RegAddr, BitMask, Data);
+}
+
+u32 rtw_hal_read_rfreg(struct adapter *padapter, u32 eRFPath, u32 RegAddr, u32 BitMask)
+{
+ u32 data = 0;
+
+ if (padapter->HalFunc.read_rfreg)
+ data = padapter->HalFunc.read_rfreg(padapter, eRFPath, RegAddr, BitMask);
+ return data;
+}
+void rtw_hal_write_rfreg(struct adapter *padapter, u32 eRFPath, u32 RegAddr, u32 BitMask, u32 Data)
+{
+ if (padapter->HalFunc.write_rfreg)
+ padapter->HalFunc.write_rfreg(padapter, eRFPath, RegAddr, BitMask, Data);
+}
+
+void rtw_hal_set_chan(struct adapter *padapter, u8 channel)
+{
+ if (padapter->HalFunc.set_channel_handler)
+ padapter->HalFunc.set_channel_handler(padapter, channel);
+}
+
+void rtw_hal_set_chnl_bw(struct adapter *padapter, u8 channel,
+ enum channel_width Bandwidth, u8 Offset40, u8 Offset80)
+{
+ if (padapter->HalFunc.set_chnl_bw_handler)
+ padapter->HalFunc.set_chnl_bw_handler(padapter, channel,
+ Bandwidth, Offset40,
+ Offset80);
+}
+
+void rtw_hal_dm_watchdog(struct adapter *padapter)
+{
+ if (padapter->HalFunc.hal_dm_watchdog)
+ padapter->HalFunc.hal_dm_watchdog(padapter);
+}
+
+void rtw_hal_dm_watchdog_in_lps(struct adapter *padapter)
+{
+ if (adapter_to_pwrctl(padapter)->fw_current_in_ps_mode) {
+ if (padapter->HalFunc.hal_dm_watchdog_in_lps)
+ padapter->HalFunc.hal_dm_watchdog_in_lps(padapter); /* this function caller is in interrupt context */
+ }
+}
+
+void beacon_timing_control(struct adapter *padapter)
+{
+ if (padapter->HalFunc.SetBeaconRelatedRegistersHandler)
+ padapter->HalFunc.SetBeaconRelatedRegistersHandler(padapter);
+}
+
+
+s32 rtw_hal_xmit_thread_handler(struct adapter *padapter)
+{
+ if (padapter->HalFunc.xmit_thread_handler)
+ return padapter->HalFunc.xmit_thread_handler(padapter);
+ return _FAIL;
+}
+
+void rtw_hal_notch_filter(struct adapter *adapter, bool enable)
+{
+ if (adapter->HalFunc.hal_notch_filter)
+ adapter->HalFunc.hal_notch_filter(adapter, enable);
+}
+
+void rtw_hal_reset_security_engine(struct adapter *adapter)
+{
+ if (adapter->HalFunc.hal_reset_security_engine)
+ adapter->HalFunc.hal_reset_security_engine(adapter);
+}
+
+bool rtw_hal_c2h_valid(struct adapter *adapter, u8 *buf)
+{
+ return c2h_evt_valid((struct c2h_evt_hdr_88xx *)buf);
+}
+
+s32 rtw_hal_c2h_handler(struct adapter *adapter, u8 *c2h_evt)
+{
+ s32 ret = _FAIL;
+
+ if (adapter->HalFunc.c2h_handler)
+ ret = adapter->HalFunc.c2h_handler(adapter, c2h_evt);
+ return ret;
+}
+
+c2h_id_filter rtw_hal_c2h_id_filter_ccx(struct adapter *adapter)
+{
+ return adapter->HalFunc.c2h_id_filter_ccx;
+}
+
+s32 rtw_hal_macid_sleep(struct adapter *padapter, u32 macid)
+{
+ u8 support;
+
+ support = false;
+ rtw_hal_get_def_var(padapter, HAL_DEF_MACID_SLEEP, &support);
+ if (false == support)
+ return _FAIL;
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_MACID_SLEEP, (u8 *)&macid);
+
+ return _SUCCESS;
+}
+
+s32 rtw_hal_macid_wakeup(struct adapter *padapter, u32 macid)
+{
+ u8 support;
+
+ support = false;
+ rtw_hal_get_def_var(padapter, HAL_DEF_MACID_SLEEP, &support);
+ if (false == support)
+ return _FAIL;
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_MACID_WAKEUP, (u8 *)&macid);
+
+ return _SUCCESS;
+}
+
+s32 rtw_hal_fill_h2c_cmd(struct adapter *padapter, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer)
+{
+ s32 ret = _FAIL;
+
+ if (padapter->HalFunc.fill_h2c_cmd)
+ ret = padapter->HalFunc.fill_h2c_cmd(padapter, ElementID, CmdLen, pCmdBuffer);
+
+ return ret;
+}
diff --git a/drivers/staging/rtl8723bs/hal/hal_pwr_seq.c b/drivers/staging/rtl8723bs/hal/hal_pwr_seq.c
new file mode 100644
index 000000000..fba67a7c0
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/hal_pwr_seq.c
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+/*
+*
+This file includes all kinds of Power Action event for RTL8723B
+and corresponding hardware configurtions which are released from HW SD.
+
+Major Change History:
+ When Who What
+ ---------- --------------- -------------------------------
+ 2011-08-08 Roger Create.
+
+*/
+
+#include "hal_pwr_seq.h"
+
+/* drivers should parse below arrays and do the corresponding actions */
+/* 3 Power on Array */
+struct wlan_pwr_cfg rtl8723B_power_on_flow[
+ RTL8723B_TRANS_CARDEMU_TO_ACT_STEPS+
+ RTL8723B_TRANS_END_STEPS
+] = {
+ RTL8723B_TRANS_CARDEMU_TO_ACT
+ RTL8723B_TRANS_END
+};
+
+/* 3Radio off GPIO Array */
+struct wlan_pwr_cfg rtl8723B_radio_off_flow[
+ RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS+
+ RTL8723B_TRANS_END_STEPS
+] = {
+ RTL8723B_TRANS_ACT_TO_CARDEMU
+ RTL8723B_TRANS_END
+};
+
+/* 3Card Disable Array */
+struct wlan_pwr_cfg rtl8723B_card_disable_flow[
+ RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS+
+ RTL8723B_TRANS_CARDEMU_TO_PDN_STEPS+
+ RTL8723B_TRANS_END_STEPS
+] = {
+ RTL8723B_TRANS_ACT_TO_CARDEMU
+ RTL8723B_TRANS_CARDEMU_TO_CARDDIS
+ RTL8723B_TRANS_END
+};
+
+/* 3 Card Enable Array */
+struct wlan_pwr_cfg rtl8723B_card_enable_flow[
+ RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS+
+ RTL8723B_TRANS_CARDEMU_TO_PDN_STEPS+
+ RTL8723B_TRANS_END_STEPS
+] = {
+ RTL8723B_TRANS_CARDDIS_TO_CARDEMU
+ RTL8723B_TRANS_CARDEMU_TO_ACT
+ RTL8723B_TRANS_END
+};
+
+/* 3Suspend Array */
+struct wlan_pwr_cfg rtl8723B_suspend_flow[
+ RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS+
+ RTL8723B_TRANS_CARDEMU_TO_SUS_STEPS+
+ RTL8723B_TRANS_END_STEPS
+] = {
+ RTL8723B_TRANS_ACT_TO_CARDEMU
+ RTL8723B_TRANS_CARDEMU_TO_SUS
+ RTL8723B_TRANS_END
+};
+
+/* 3 Resume Array */
+struct wlan_pwr_cfg rtl8723B_resume_flow[
+ RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS+
+ RTL8723B_TRANS_CARDEMU_TO_SUS_STEPS+
+ RTL8723B_TRANS_END_STEPS
+] = {
+ RTL8723B_TRANS_SUS_TO_CARDEMU
+ RTL8723B_TRANS_CARDEMU_TO_ACT
+ RTL8723B_TRANS_END
+};
+
+/* 3HWPDN Array */
+struct wlan_pwr_cfg rtl8723B_hwpdn_flow[
+ RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS+
+ RTL8723B_TRANS_CARDEMU_TO_PDN_STEPS+
+ RTL8723B_TRANS_END_STEPS
+] = {
+ RTL8723B_TRANS_ACT_TO_CARDEMU
+ RTL8723B_TRANS_CARDEMU_TO_PDN
+ RTL8723B_TRANS_END
+};
+
+/* 3 Enter LPS */
+struct wlan_pwr_cfg rtl8723B_enter_lps_flow[
+ RTL8723B_TRANS_ACT_TO_LPS_STEPS+RTL8723B_TRANS_END_STEPS
+] = {
+ /* FW behavior */
+ RTL8723B_TRANS_ACT_TO_LPS
+ RTL8723B_TRANS_END
+};
+
+/* 3 Leave LPS */
+struct wlan_pwr_cfg rtl8723B_leave_lps_flow[
+ RTL8723B_TRANS_LPS_TO_ACT_STEPS+RTL8723B_TRANS_END_STEPS
+] = {
+ /* FW behavior */
+ RTL8723B_TRANS_LPS_TO_ACT
+ RTL8723B_TRANS_END
+};
+
+/* 3 Enter SW LPS */
+struct wlan_pwr_cfg rtl8723B_enter_swlps_flow[
+ RTL8723B_TRANS_ACT_TO_SWLPS_STEPS+RTL8723B_TRANS_END_STEPS
+] = {
+ /* SW behavior */
+ RTL8723B_TRANS_ACT_TO_SWLPS
+ RTL8723B_TRANS_END
+};
+
+/* 3 Leave SW LPS */
+struct wlan_pwr_cfg rtl8723B_leave_swlps_flow[
+ RTL8723B_TRANS_SWLPS_TO_ACT_STEPS+RTL8723B_TRANS_END_STEPS
+] = {
+ /* SW behavior */
+ RTL8723B_TRANS_SWLPS_TO_ACT
+ RTL8723B_TRANS_END
+};
diff --git a/drivers/staging/rtl8723bs/hal/hal_sdio.c b/drivers/staging/rtl8723bs/hal/hal_sdio.c
new file mode 100644
index 000000000..9de62a0f5
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/hal_sdio.c
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include <drv_types.h>
+#include <rtw_debug.h>
+#include <hal_data.h>
+
+u8 rtw_hal_sdio_max_txoqt_free_space(struct adapter *padapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+
+ if (pHalData->SdioTxOQTMaxFreeSpace < 8)
+ pHalData->SdioTxOQTMaxFreeSpace = 8;
+
+ return pHalData->SdioTxOQTMaxFreeSpace;
+}
+
+u8 rtw_hal_sdio_query_tx_freepage(
+ struct adapter *padapter, u8 PageIdx, u8 RequiredPageNum
+)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+
+ if ((pHalData->SdioTxFIFOFreePage[PageIdx]+pHalData->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX]) >= (RequiredPageNum))
+ return true;
+ else
+ return false;
+}
+
+void rtw_hal_sdio_update_tx_freepage(
+ struct adapter *padapter, u8 PageIdx, u8 RequiredPageNum
+)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ u8 DedicatedPgNum = 0;
+ u8 RequiredPublicFreePgNum = 0;
+ /* _irqL irql; */
+
+ /* spin_lock_bh(&pHalData->SdioTxFIFOFreePageLock); */
+
+ DedicatedPgNum = pHalData->SdioTxFIFOFreePage[PageIdx];
+ if (RequiredPageNum <= DedicatedPgNum) {
+ pHalData->SdioTxFIFOFreePage[PageIdx] -= RequiredPageNum;
+ } else {
+ pHalData->SdioTxFIFOFreePage[PageIdx] = 0;
+ RequiredPublicFreePgNum = RequiredPageNum - DedicatedPgNum;
+ pHalData->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX] -= RequiredPublicFreePgNum;
+ }
+
+ /* spin_unlock_bh(&pHalData->SdioTxFIFOFreePageLock); */
+}
+
+void rtw_hal_set_sdio_tx_max_length(
+ struct adapter *padapter, u8 numHQ, u8 numNQ, u8 numLQ, u8 numPubQ
+)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ u32 page_size;
+ u32 lenHQ, lenNQ, lenLQ;
+
+ rtw_hal_get_def_var(padapter, HAL_DEF_TX_PAGE_SIZE, &page_size);
+
+ lenHQ = ((numHQ + numPubQ) >> 1) * page_size;
+ lenNQ = ((numNQ + numPubQ) >> 1) * page_size;
+ lenLQ = ((numLQ + numPubQ) >> 1) * page_size;
+
+ pHalData->sdio_tx_max_len[HI_QUEUE_IDX] =
+ (lenHQ > MAX_XMITBUF_SZ) ? MAX_XMITBUF_SZ : lenHQ;
+ pHalData->sdio_tx_max_len[MID_QUEUE_IDX] =
+ (lenNQ > MAX_XMITBUF_SZ) ? MAX_XMITBUF_SZ : lenNQ;
+ pHalData->sdio_tx_max_len[LOW_QUEUE_IDX] =
+ (lenLQ > MAX_XMITBUF_SZ) ? MAX_XMITBUF_SZ : lenLQ;
+}
+
+u32 rtw_hal_get_sdio_tx_max_length(struct adapter *padapter, u8 queue_idx)
+{
+ struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ u32 deviceId, max_len;
+
+
+ deviceId = ffaddr2deviceId(pdvobjpriv, queue_idx);
+ switch (deviceId) {
+ case WLAN_TX_HIQ_DEVICE_ID:
+ max_len = pHalData->sdio_tx_max_len[HI_QUEUE_IDX];
+ break;
+
+ case WLAN_TX_MIQ_DEVICE_ID:
+ max_len = pHalData->sdio_tx_max_len[MID_QUEUE_IDX];
+ break;
+
+ case WLAN_TX_LOQ_DEVICE_ID:
+ max_len = pHalData->sdio_tx_max_len[LOW_QUEUE_IDX];
+ break;
+
+ default:
+ max_len = pHalData->sdio_tx_max_len[MID_QUEUE_IDX];
+ break;
+ }
+
+ return max_len;
+}
diff --git a/drivers/staging/rtl8723bs/hal/odm.c b/drivers/staging/rtl8723bs/hal/odm.c
new file mode 100644
index 000000000..31f65d817
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/odm.c
@@ -0,0 +1,1197 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include "odm_precomp.h"
+
+/* Global var */
+
+u32 OFDMSwingTable[OFDM_TABLE_SIZE] = {
+ 0x7f8001fe, /* 0, +6.0dB */
+ 0x788001e2, /* 1, +5.5dB */
+ 0x71c001c7, /* 2, +5.0dB */
+ 0x6b8001ae, /* 3, +4.5dB */
+ 0x65400195, /* 4, +4.0dB */
+ 0x5fc0017f, /* 5, +3.5dB */
+ 0x5a400169, /* 6, +3.0dB */
+ 0x55400155, /* 7, +2.5dB */
+ 0x50800142, /* 8, +2.0dB */
+ 0x4c000130, /* 9, +1.5dB */
+ 0x47c0011f, /* 10, +1.0dB */
+ 0x43c0010f, /* 11, +0.5dB */
+ 0x40000100, /* 12, +0dB */
+ 0x3c8000f2, /* 13, -0.5dB */
+ 0x390000e4, /* 14, -1.0dB */
+ 0x35c000d7, /* 15, -1.5dB */
+ 0x32c000cb, /* 16, -2.0dB */
+ 0x300000c0, /* 17, -2.5dB */
+ 0x2d4000b5, /* 18, -3.0dB */
+ 0x2ac000ab, /* 19, -3.5dB */
+ 0x288000a2, /* 20, -4.0dB */
+ 0x26000098, /* 21, -4.5dB */
+ 0x24000090, /* 22, -5.0dB */
+ 0x22000088, /* 23, -5.5dB */
+ 0x20000080, /* 24, -6.0dB */
+ 0x1e400079, /* 25, -6.5dB */
+ 0x1c800072, /* 26, -7.0dB */
+ 0x1b00006c, /* 27. -7.5dB */
+ 0x19800066, /* 28, -8.0dB */
+ 0x18000060, /* 29, -8.5dB */
+ 0x16c0005b, /* 30, -9.0dB */
+ 0x15800056, /* 31, -9.5dB */
+ 0x14400051, /* 32, -10.0dB */
+ 0x1300004c, /* 33, -10.5dB */
+ 0x12000048, /* 34, -11.0dB */
+ 0x11000044, /* 35, -11.5dB */
+ 0x10000040, /* 36, -12.0dB */
+};
+
+u8 CCKSwingTable_Ch1_Ch13[CCK_TABLE_SIZE][8] = {
+ {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, /* 0, +0dB */
+ {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 1, -0.5dB */
+ {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 2, -1.0dB */
+ {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 3, -1.5dB */
+ {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 4, -2.0dB */
+ {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 5, -2.5dB */
+ {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 6, -3.0dB */
+ {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 7, -3.5dB */
+ {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 8, -4.0dB */
+ {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 9, -4.5dB */
+ {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 10, -5.0dB */
+ {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 11, -5.5dB */
+ {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 12, -6.0dB <== default */
+ {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 13, -6.5dB */
+ {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 14, -7.0dB */
+ {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 15, -7.5dB */
+ {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */
+ {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 17, -8.5dB */
+ {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 18, -9.0dB */
+ {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 19, -9.5dB */
+ {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 20, -10.0dB */
+ {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 21, -10.5dB */
+ {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 22, -11.0dB */
+ {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 23, -11.5dB */
+ {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 24, -12.0dB */
+ {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 25, -12.5dB */
+ {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 26, -13.0dB */
+ {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 27, -13.5dB */
+ {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 28, -14.0dB */
+ {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 29, -14.5dB */
+ {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 30, -15.0dB */
+ {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 31, -15.5dB */
+ {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} /* 32, -16.0dB */
+};
+
+u8 CCKSwingTable_Ch14[CCK_TABLE_SIZE][8] = {
+ {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, /* 0, +0dB */
+ {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 1, -0.5dB */
+ {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 2, -1.0dB */
+ {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 3, -1.5dB */
+ {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 4, -2.0dB */
+ {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 5, -2.5dB */
+ {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 6, -3.0dB */
+ {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 7, -3.5dB */
+ {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 8, -4.0dB */
+ {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 9, -4.5dB */
+ {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 10, -5.0dB */
+ {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 11, -5.5dB */
+ {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 12, -6.0dB <== default */
+ {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 13, -6.5dB */
+ {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 14, -7.0dB */
+ {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 15, -7.5dB */
+ {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */
+ {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 17, -8.5dB */
+ {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 18, -9.0dB */
+ {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 19, -9.5dB */
+ {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 20, -10.0dB */
+ {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 21, -10.5dB */
+ {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 22, -11.0dB */
+ {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 23, -11.5dB */
+ {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 24, -12.0dB */
+ {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 25, -12.5dB */
+ {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 26, -13.0dB */
+ {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 27, -13.5dB */
+ {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 28, -14.0dB */
+ {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 29, -14.5dB */
+ {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 30, -15.0dB */
+ {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 31, -15.5dB */
+ {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} /* 32, -16.0dB */
+};
+
+u32 OFDMSwingTable_New[OFDM_TABLE_SIZE] = {
+ 0x0b40002d, /* 0, -15.0dB */
+ 0x0c000030, /* 1, -14.5dB */
+ 0x0cc00033, /* 2, -14.0dB */
+ 0x0d800036, /* 3, -13.5dB */
+ 0x0e400039, /* 4, -13.0dB */
+ 0x0f00003c, /* 5, -12.5dB */
+ 0x10000040, /* 6, -12.0dB */
+ 0x11000044, /* 7, -11.5dB */
+ 0x12000048, /* 8, -11.0dB */
+ 0x1300004c, /* 9, -10.5dB */
+ 0x14400051, /* 10, -10.0dB */
+ 0x15800056, /* 11, -9.5dB */
+ 0x16c0005b, /* 12, -9.0dB */
+ 0x18000060, /* 13, -8.5dB */
+ 0x19800066, /* 14, -8.0dB */
+ 0x1b00006c, /* 15, -7.5dB */
+ 0x1c800072, /* 16, -7.0dB */
+ 0x1e400079, /* 17, -6.5dB */
+ 0x20000080, /* 18, -6.0dB */
+ 0x22000088, /* 19, -5.5dB */
+ 0x24000090, /* 20, -5.0dB */
+ 0x26000098, /* 21, -4.5dB */
+ 0x288000a2, /* 22, -4.0dB */
+ 0x2ac000ab, /* 23, -3.5dB */
+ 0x2d4000b5, /* 24, -3.0dB */
+ 0x300000c0, /* 25, -2.5dB */
+ 0x32c000cb, /* 26, -2.0dB */
+ 0x35c000d7, /* 27, -1.5dB */
+ 0x390000e4, /* 28, -1.0dB */
+ 0x3c8000f2, /* 29, -0.5dB */
+ 0x40000100, /* 30, +0dB */
+ 0x43c0010f, /* 31, +0.5dB */
+ 0x47c0011f, /* 32, +1.0dB */
+ 0x4c000130, /* 33, +1.5dB */
+ 0x50800142, /* 34, +2.0dB */
+ 0x55400155, /* 35, +2.5dB */
+ 0x5a400169, /* 36, +3.0dB */
+ 0x5fc0017f, /* 37, +3.5dB */
+ 0x65400195, /* 38, +4.0dB */
+ 0x6b8001ae, /* 39, +4.5dB */
+ 0x71c001c7, /* 40, +5.0dB */
+ 0x788001e2, /* 41, +5.5dB */
+ 0x7f8001fe /* 42, +6.0dB */
+};
+
+u8 CCKSwingTable_Ch1_Ch13_New[CCK_TABLE_SIZE][8] = {
+ {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}, /* 0, -16.0dB */
+ {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 1, -15.5dB */
+ {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 2, -15.0dB */
+ {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 3, -14.5dB */
+ {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 4, -14.0dB */
+ {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 5, -13.5dB */
+ {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 6, -13.0dB */
+ {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 7, -12.5dB */
+ {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 8, -12.0dB */
+ {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 9, -11.5dB */
+ {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 10, -11.0dB */
+ {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 11, -10.5dB */
+ {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 12, -10.0dB */
+ {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 13, -9.5dB */
+ {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 14, -9.0dB */
+ {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 15, -8.5dB */
+ {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */
+ {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 17, -7.5dB */
+ {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 18, -7.0dB */
+ {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 19, -6.5dB */
+ {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 20, -6.0dB */
+ {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 21, -5.5dB */
+ {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 22, -5.0dB */
+ {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 23, -4.5dB */
+ {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 24, -4.0dB */
+ {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 25, -3.5dB */
+ {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 26, -3.0dB */
+ {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 27, -2.5dB */
+ {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 28, -2.0dB */
+ {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 29, -1.5dB */
+ {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 30, -1.0dB */
+ {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 31, -0.5dB */
+ {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04} /* 32, +0dB */
+};
+
+u8 CCKSwingTable_Ch14_New[CCK_TABLE_SIZE][8] = {
+ {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}, /* 0, -16.0dB */
+ {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 1, -15.5dB */
+ {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 2, -15.0dB */
+ {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 3, -14.5dB */
+ {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 4, -14.0dB */
+ {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 5, -13.5dB */
+ {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 6, -13.0dB */
+ {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 7, -12.5dB */
+ {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 8, -12.0dB */
+ {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 9, -11.5dB */
+ {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 10, -11.0dB */
+ {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 11, -10.5dB */
+ {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 12, -10.0dB */
+ {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 13, -9.5dB */
+ {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 14, -9.0dB */
+ {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 15, -8.5dB */
+ {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */
+ {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 17, -7.5dB */
+ {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 18, -7.0dB */
+ {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 19, -6.5dB */
+ {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 20, -6.0dB */
+ {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 21, -5.5dB */
+ {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 22, -5.0dB */
+ {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 23, -4.5dB */
+ {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 24, -4.0dB */
+ {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 25, -3.5dB */
+ {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 26, -3.0dB */
+ {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 27, -2.5dB */
+ {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 28, -2.0dB */
+ {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 29, -1.5dB */
+ {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 30, -1.0dB */
+ {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 31, -0.5dB */
+ {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00} /* 32, +0dB */
+};
+
+u32 TxScalingTable_Jaguar[TXSCALE_TABLE_SIZE] = {
+ 0x081, /* 0, -12.0dB */
+ 0x088, /* 1, -11.5dB */
+ 0x090, /* 2, -11.0dB */
+ 0x099, /* 3, -10.5dB */
+ 0x0A2, /* 4, -10.0dB */
+ 0x0AC, /* 5, -9.5dB */
+ 0x0B6, /* 6, -9.0dB */
+ 0x0C0, /* 7, -8.5dB */
+ 0x0CC, /* 8, -8.0dB */
+ 0x0D8, /* 9, -7.5dB */
+ 0x0E5, /* 10, -7.0dB */
+ 0x0F2, /* 11, -6.5dB */
+ 0x101, /* 12, -6.0dB */
+ 0x110, /* 13, -5.5dB */
+ 0x120, /* 14, -5.0dB */
+ 0x131, /* 15, -4.5dB */
+ 0x143, /* 16, -4.0dB */
+ 0x156, /* 17, -3.5dB */
+ 0x16A, /* 18, -3.0dB */
+ 0x180, /* 19, -2.5dB */
+ 0x197, /* 20, -2.0dB */
+ 0x1AF, /* 21, -1.5dB */
+ 0x1C8, /* 22, -1.0dB */
+ 0x1E3, /* 23, -0.5dB */
+ 0x200, /* 24, +0 dB */
+ 0x21E, /* 25, +0.5dB */
+ 0x23E, /* 26, +1.0dB */
+ 0x261, /* 27, +1.5dB */
+ 0x285, /* 28, +2.0dB */
+ 0x2AB, /* 29, +2.5dB */
+ 0x2D3, /* 30, +3.0dB */
+ 0x2FE, /* 31, +3.5dB */
+ 0x32B, /* 32, +4.0dB */
+ 0x35C, /* 33, +4.5dB */
+ 0x38E, /* 34, +5.0dB */
+ 0x3C4, /* 35, +5.5dB */
+ 0x3FE /* 36, +6.0dB */
+};
+
+/* Remove Edca by Yu Chen */
+
+static void odm_CommonInfoSelfInit(struct dm_odm_t *pDM_Odm)
+{
+ pDM_Odm->bCckHighPower = (bool) PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG(CCK_RPT_FORMAT, pDM_Odm), ODM_BIT(CCK_RPT_FORMAT, pDM_Odm));
+ pDM_Odm->RFPathRxEnable = (u8) PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG(BB_RX_PATH, pDM_Odm), ODM_BIT(BB_RX_PATH, pDM_Odm));
+
+ pDM_Odm->TxRate = 0xFF;
+}
+
+static void odm_CommonInfoSelfUpdate(struct dm_odm_t *pDM_Odm)
+{
+ u8 EntryCnt = 0;
+ u8 i;
+ PSTA_INFO_T pEntry;
+
+ if (*(pDM_Odm->pBandWidth) == ODM_BW40M) {
+ if (*(pDM_Odm->pSecChOffset) == 1)
+ pDM_Odm->ControlChannel = *(pDM_Odm->pChannel)-2;
+ else if (*(pDM_Odm->pSecChOffset) == 2)
+ pDM_Odm->ControlChannel = *(pDM_Odm->pChannel)+2;
+ } else
+ pDM_Odm->ControlChannel = *(pDM_Odm->pChannel);
+
+ for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
+ pEntry = pDM_Odm->pODM_StaInfo[i];
+ if (IS_STA_VALID(pEntry))
+ EntryCnt++;
+ }
+
+ if (EntryCnt == 1)
+ pDM_Odm->bOneEntryOnly = true;
+ else
+ pDM_Odm->bOneEntryOnly = false;
+}
+
+static void odm_CmnInfoInit_Debug(struct dm_odm_t *pDM_Odm)
+{
+}
+
+static void odm_BasicDbgMessage(struct dm_odm_t *pDM_Odm)
+{
+}
+
+/* 3 ============================================================ */
+/* 3 RATR MASK */
+/* 3 ============================================================ */
+/* 3 ============================================================ */
+/* 3 Rate Adaptive */
+/* 3 ============================================================ */
+
+static void odm_RateAdaptiveMaskInit(struct dm_odm_t *pDM_Odm)
+{
+ struct odm_rate_adaptive *pOdmRA = &pDM_Odm->RateAdaptive;
+
+ pOdmRA->Type = DM_Type_ByDriver;
+ if (pOdmRA->Type == DM_Type_ByDriver)
+ pDM_Odm->bUseRAMask = true;
+ else
+ pDM_Odm->bUseRAMask = false;
+
+ pOdmRA->RATRState = DM_RATR_STA_INIT;
+ pOdmRA->LdpcThres = 35;
+ pOdmRA->bUseLdpc = false;
+ pOdmRA->HighRSSIThresh = 50;
+ pOdmRA->LowRSSIThresh = 20;
+}
+
+u32 ODM_Get_Rate_Bitmap(
+ struct dm_odm_t *pDM_Odm,
+ u32 macid,
+ u32 ra_mask,
+ u8 rssi_level
+)
+{
+ PSTA_INFO_T pEntry;
+ u32 rate_bitmap = 0;
+ u8 WirelessMode;
+
+ pEntry = pDM_Odm->pODM_StaInfo[macid];
+ if (!IS_STA_VALID(pEntry))
+ return ra_mask;
+
+ WirelessMode = pEntry->wireless_mode;
+
+ switch (WirelessMode) {
+ case ODM_WM_B:
+ if (ra_mask & 0x0000000c) /* 11M or 5.5M enable */
+ rate_bitmap = 0x0000000d;
+ else
+ rate_bitmap = 0x0000000f;
+ break;
+
+ case (ODM_WM_G):
+ if (rssi_level == DM_RATR_STA_HIGH)
+ rate_bitmap = 0x00000f00;
+ else
+ rate_bitmap = 0x00000ff0;
+ break;
+
+ case (ODM_WM_B|ODM_WM_G):
+ if (rssi_level == DM_RATR_STA_HIGH)
+ rate_bitmap = 0x00000f00;
+ else if (rssi_level == DM_RATR_STA_MIDDLE)
+ rate_bitmap = 0x00000ff0;
+ else
+ rate_bitmap = 0x00000ff5;
+ break;
+
+ case (ODM_WM_B|ODM_WM_G|ODM_WM_N24G):
+ case (ODM_WM_B|ODM_WM_N24G):
+ case (ODM_WM_G|ODM_WM_N24G):
+ if (rssi_level == DM_RATR_STA_HIGH)
+ rate_bitmap = 0x000f0000;
+ else if (rssi_level == DM_RATR_STA_MIDDLE)
+ rate_bitmap = 0x000ff000;
+ else {
+ if (*(pDM_Odm->pBandWidth) == ODM_BW40M)
+ rate_bitmap = 0x000ff015;
+ else
+ rate_bitmap = 0x000ff005;
+ }
+ break;
+
+ default:
+ rate_bitmap = 0x0fffffff;
+ break;
+ }
+
+ return ra_mask & rate_bitmap;
+
+}
+
+static void odm_RefreshRateAdaptiveMaskCE(struct dm_odm_t *pDM_Odm)
+{
+ u8 i;
+ struct adapter *padapter = pDM_Odm->Adapter;
+
+ if (padapter->bDriverStopped) {
+ return;
+ }
+
+ if (!pDM_Odm->bUseRAMask) {
+ return;
+ }
+
+ for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
+ PSTA_INFO_T pstat = pDM_Odm->pODM_StaInfo[i];
+
+ if (IS_STA_VALID(pstat)) {
+ if (IS_MCAST(pstat->hwaddr)) /* if (psta->mac_id == 1) */
+ continue;
+
+ if (true == ODM_RAStateCheck(pDM_Odm, pstat->rssi_stat.UndecoratedSmoothedPWDB, false, &pstat->rssi_level)) {
+ /* printk("RSSI:%d, RSSI_LEVEL:%d\n", pstat->rssi_stat.UndecoratedSmoothedPWDB, pstat->rssi_level); */
+ rtw_hal_update_ra_mask(pstat, pstat->rssi_level);
+ }
+
+ }
+ }
+}
+
+/*-----------------------------------------------------------------------------
+* Function: odm_RefreshRateAdaptiveMask()
+*
+* Overview: Update rate table mask according to rssi
+*
+* Input: NONE
+*
+* Output: NONE
+*
+* Return: NONE
+*
+* Revised History:
+*When Who Remark
+*05/27/2009 hpfan Create Version 0.
+*
+* --------------------------------------------------------------------------
+*/
+static void odm_RefreshRateAdaptiveMask(struct dm_odm_t *pDM_Odm)
+{
+
+ if (!(pDM_Odm->SupportAbility & ODM_BB_RA_MASK)) {
+ return;
+ }
+ odm_RefreshRateAdaptiveMaskCE(pDM_Odm);
+}
+
+/* Return Value: bool */
+/* - true: RATRState is changed. */
+bool ODM_RAStateCheck(
+ struct dm_odm_t *pDM_Odm,
+ s32 RSSI,
+ bool bForceUpdate,
+ u8 *pRATRState
+)
+{
+ struct odm_rate_adaptive *pRA = &pDM_Odm->RateAdaptive;
+ const u8 GoUpGap = 5;
+ u8 HighRSSIThreshForRA = pRA->HighRSSIThresh;
+ u8 LowRSSIThreshForRA = pRA->LowRSSIThresh;
+ u8 RATRState;
+
+ /* Threshold Adjustment: */
+ /* when RSSI state trends to go up one or two levels, make sure RSSI is high enough. */
+ /* Here GoUpGap is added to solve the boundary's level alternation issue. */
+ switch (*pRATRState) {
+ case DM_RATR_STA_INIT:
+ case DM_RATR_STA_HIGH:
+ break;
+
+ case DM_RATR_STA_MIDDLE:
+ HighRSSIThreshForRA += GoUpGap;
+ break;
+
+ case DM_RATR_STA_LOW:
+ HighRSSIThreshForRA += GoUpGap;
+ LowRSSIThreshForRA += GoUpGap;
+ break;
+
+ default:
+ netdev_dbg(pDM_Odm->Adapter->pnetdev,
+ "wrong rssi level setting %d !", *pRATRState);
+ break;
+ }
+
+ /* Decide RATRState by RSSI. */
+ if (RSSI > HighRSSIThreshForRA)
+ RATRState = DM_RATR_STA_HIGH;
+ else if (RSSI > LowRSSIThreshForRA)
+ RATRState = DM_RATR_STA_MIDDLE;
+ else
+ RATRState = DM_RATR_STA_LOW;
+ /* printk("==>%s, RATRState:0x%02x , RSSI:%d\n", __func__, RATRState, RSSI); */
+
+ if (*pRATRState != RATRState || bForceUpdate) {
+ *pRATRState = RATRState;
+ return true;
+ }
+
+ return false;
+}
+
+/* */
+
+/* 3 ============================================================ */
+/* 3 RSSI Monitor */
+/* 3 ============================================================ */
+
+static void odm_RSSIMonitorInit(struct dm_odm_t *pDM_Odm)
+{
+ struct ra_t *pRA_Table = &pDM_Odm->DM_RA_Table;
+
+ pRA_Table->firstconnect = false;
+
+}
+
+static void FindMinimumRSSI(struct adapter *padapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct dm_priv *pdmpriv = &pHalData->dmpriv;
+ struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
+
+ /* 1 1.Determine the minimum RSSI */
+
+ if (
+ (pDM_Odm->bLinked != true) &&
+ (pdmpriv->EntryMinUndecoratedSmoothedPWDB == 0)
+ ) {
+ pdmpriv->MinUndecoratedPWDBForDM = 0;
+ } else
+ pdmpriv->MinUndecoratedPWDBForDM = pdmpriv->EntryMinUndecoratedSmoothedPWDB;
+}
+
+static void odm_RSSIMonitorCheckCE(struct dm_odm_t *pDM_Odm)
+{
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+ struct dm_priv *pdmpriv = &pHalData->dmpriv;
+ int i;
+ int tmpEntryMaxPWDB = 0, tmpEntryMinPWDB = 0xff;
+ u8 sta_cnt = 0;
+ u32 PWDB_rssi[NUM_STA] = {0};/* 0~15]:MACID, [16~31]:PWDB_rssi */
+ struct ra_t *pRA_Table = &pDM_Odm->DM_RA_Table;
+
+ if (pDM_Odm->bLinked != true)
+ return;
+
+ pRA_Table->firstconnect = pDM_Odm->bLinked;
+
+ /* if (check_fwstate(&Adapter->mlmepriv, WIFI_AP_STATE|WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE) == true) */
+ {
+ struct sta_info *psta;
+
+ for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
+ psta = pDM_Odm->pODM_StaInfo[i];
+ if (IS_STA_VALID(psta)) {
+ if (IS_MCAST(psta->hwaddr)) /* if (psta->mac_id == 1) */
+ continue;
+
+ if (psta->rssi_stat.UndecoratedSmoothedPWDB == (-1))
+ continue;
+
+ if (psta->rssi_stat.UndecoratedSmoothedPWDB < tmpEntryMinPWDB)
+ tmpEntryMinPWDB = psta->rssi_stat.UndecoratedSmoothedPWDB;
+
+ if (psta->rssi_stat.UndecoratedSmoothedPWDB > tmpEntryMaxPWDB)
+ tmpEntryMaxPWDB = psta->rssi_stat.UndecoratedSmoothedPWDB;
+
+ if (psta->rssi_stat.UndecoratedSmoothedPWDB != (-1))
+ PWDB_rssi[sta_cnt++] = (psta->mac_id | (psta->rssi_stat.UndecoratedSmoothedPWDB<<16));
+ }
+ }
+
+ /* printk("%s ==> sta_cnt(%d)\n", __func__, sta_cnt); */
+
+ for (i = 0; i < sta_cnt; i++) {
+ if (PWDB_rssi[i] != (0)) {
+ if (pHalData->fw_ractrl == true)/* Report every sta's RSSI to FW */
+ rtl8723b_set_rssi_cmd(Adapter, (u8 *)(&PWDB_rssi[i]));
+ }
+ }
+ }
+
+
+
+ if (tmpEntryMaxPWDB != 0) /* If associated entry is found */
+ pdmpriv->EntryMaxUndecoratedSmoothedPWDB = tmpEntryMaxPWDB;
+ else
+ pdmpriv->EntryMaxUndecoratedSmoothedPWDB = 0;
+
+ if (tmpEntryMinPWDB != 0xff) /* If associated entry is found */
+ pdmpriv->EntryMinUndecoratedSmoothedPWDB = tmpEntryMinPWDB;
+ else
+ pdmpriv->EntryMinUndecoratedSmoothedPWDB = 0;
+
+ FindMinimumRSSI(Adapter);/* get pdmpriv->MinUndecoratedPWDBForDM */
+
+ pDM_Odm->RSSI_Min = pdmpriv->MinUndecoratedPWDBForDM;
+ /* ODM_CmnInfoUpdate(&pHalData->odmpriv , ODM_CMNINFO_RSSI_MIN, pdmpriv->MinUndecoratedPWDBForDM); */
+}
+
+static void odm_RSSIMonitorCheck(struct dm_odm_t *pDM_Odm)
+{
+ if (!(pDM_Odm->SupportAbility & ODM_BB_RSSI_MONITOR))
+ return;
+
+ odm_RSSIMonitorCheckCE(pDM_Odm);
+
+} /* odm_RSSIMonitorCheck */
+
+/* 3 ============================================================ */
+/* 3 SW Antenna Diversity */
+/* 3 ============================================================ */
+static void odm_SwAntDetectInit(struct dm_odm_t *pDM_Odm)
+{
+ struct swat_t *pDM_SWAT_Table = &pDM_Odm->DM_SWAT_Table;
+
+ pDM_SWAT_Table->SWAS_NoLink_BK_Reg92c = rtw_read32(pDM_Odm->Adapter, rDPDT_control);
+ pDM_SWAT_Table->PreAntenna = MAIN_ANT;
+ pDM_SWAT_Table->CurAntenna = MAIN_ANT;
+ pDM_SWAT_Table->SWAS_NoLink_State = 0;
+}
+
+/* 3 ============================================================ */
+/* 3 Tx Power Tracking */
+/* 3 ============================================================ */
+
+static u8 getSwingIndex(struct dm_odm_t *pDM_Odm)
+{
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ u8 i = 0;
+ u32 bbSwing;
+ u32 swingTableSize;
+ u32 *pSwingTable;
+
+ bbSwing = PHY_QueryBBReg(Adapter, rOFDM0_XATxIQImbalance, 0xFFC00000);
+
+ pSwingTable = OFDMSwingTable_New;
+ swingTableSize = OFDM_TABLE_SIZE;
+
+ for (i = 0; i < swingTableSize; ++i) {
+ u32 tableValue = pSwingTable[i];
+
+ if (tableValue >= 0x100000)
+ tableValue >>= 22;
+ if (bbSwing == tableValue)
+ break;
+ }
+ return i;
+}
+
+void odm_TXPowerTrackingInit(struct dm_odm_t *pDM_Odm)
+{
+ u8 defaultSwingIndex = getSwingIndex(pDM_Odm);
+ u8 p = 0;
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+
+
+ struct dm_priv *pdmpriv = &pHalData->dmpriv;
+
+ pdmpriv->bTXPowerTracking = true;
+ pdmpriv->TXPowercount = 0;
+ pdmpriv->bTXPowerTrackingInit = false;
+
+ if (*(pDM_Odm->mp_mode) != 1)
+ pdmpriv->TxPowerTrackControl = true;
+ else
+ pdmpriv->TxPowerTrackControl = false;
+
+ /* pDM_Odm->RFCalibrateInfo.TxPowerTrackControl = true; */
+ pDM_Odm->RFCalibrateInfo.ThermalValue = pHalData->EEPROMThermalMeter;
+ pDM_Odm->RFCalibrateInfo.ThermalValue_IQK = pHalData->EEPROMThermalMeter;
+ pDM_Odm->RFCalibrateInfo.ThermalValue_LCK = pHalData->EEPROMThermalMeter;
+
+ /* The index of "0 dB" in SwingTable. */
+ pDM_Odm->DefaultOfdmIndex = (defaultSwingIndex >= OFDM_TABLE_SIZE) ? 30 : defaultSwingIndex;
+ pDM_Odm->DefaultCckIndex = 20;
+
+ pDM_Odm->BbSwingIdxCckBase = pDM_Odm->DefaultCckIndex;
+ pDM_Odm->RFCalibrateInfo.CCK_index = pDM_Odm->DefaultCckIndex;
+
+ for (p = RF_PATH_A; p < MAX_RF_PATH; ++p) {
+ pDM_Odm->BbSwingIdxOfdmBase[p] = pDM_Odm->DefaultOfdmIndex;
+ pDM_Odm->RFCalibrateInfo.OFDM_index[p] = pDM_Odm->DefaultOfdmIndex;
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[p] = 0;
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[p] = 0;
+ pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p] = 0;
+ }
+
+}
+
+void ODM_TXPowerTrackingCheck(struct dm_odm_t *pDM_Odm)
+{
+ struct adapter *Adapter = pDM_Odm->Adapter;
+
+ if (!(pDM_Odm->SupportAbility & ODM_RF_TX_PWR_TRACK))
+ return;
+
+ if (!pDM_Odm->RFCalibrateInfo.TM_Trigger) { /* at least delay 1 sec */
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_T_METER_NEW, (BIT17 | BIT16), 0x03);
+
+ pDM_Odm->RFCalibrateInfo.TM_Trigger = 1;
+ return;
+ } else {
+ ODM_TXPowerTrackingCallback_ThermalMeter(Adapter);
+ pDM_Odm->RFCalibrateInfo.TM_Trigger = 0;
+ }
+}
+
+/* */
+/* 3 Export Interface */
+/* */
+
+/* */
+/* 2011/09/21 MH Add to describe different team necessary resource allocate?? */
+/* */
+void ODM_DMInit(struct dm_odm_t *pDM_Odm)
+{
+
+ odm_CommonInfoSelfInit(pDM_Odm);
+ odm_CmnInfoInit_Debug(pDM_Odm);
+ odm_DIGInit(pDM_Odm);
+ odm_NHMCounterStatisticsInit(pDM_Odm);
+ odm_AdaptivityInit(pDM_Odm);
+ odm_RateAdaptiveMaskInit(pDM_Odm);
+ ODM_CfoTrackingInit(pDM_Odm);
+ ODM_EdcaTurboInit(pDM_Odm);
+ odm_RSSIMonitorInit(pDM_Odm);
+ odm_TXPowerTrackingInit(pDM_Odm);
+
+ ODM_ClearTxPowerTrackingState(pDM_Odm);
+
+ odm_DynamicBBPowerSavingInit(pDM_Odm);
+ odm_DynamicTxPowerInit(pDM_Odm);
+
+ odm_SwAntDetectInit(pDM_Odm);
+}
+
+/* */
+/* 2011/09/20 MH This is the entry pointer for all team to execute HW out source DM. */
+/* You can not add any dummy function here, be care, you can only use DM structure */
+/* to perform any new ODM_DM. */
+/* */
+void ODM_DMWatchdog(struct dm_odm_t *pDM_Odm)
+{
+ odm_CommonInfoSelfUpdate(pDM_Odm);
+ odm_BasicDbgMessage(pDM_Odm);
+ odm_FalseAlarmCounterStatistics(pDM_Odm);
+ odm_NHMCounterStatistics(pDM_Odm);
+
+ odm_RSSIMonitorCheck(pDM_Odm);
+
+ /* For CE Platform(SPRD or Tablet) */
+ /* 8723A or 8189ES platform */
+ /* NeilChen--2012--08--24-- */
+ /* Fix Leave LPS issue */
+ if ((adapter_to_pwrctl(pDM_Odm->Adapter)->pwr_mode != PS_MODE_ACTIVE) /* in LPS mode */
+ /* */
+ /* (pDM_Odm->SupportICType & (ODM_RTL8723A))|| */
+ /* (pDM_Odm->SupportICType & (ODM_RTL8188E) &&(&&(((pDM_Odm->SupportInterface == ODM_ITRF_SDIO))) */
+ /* */
+ ) {
+ odm_DIGbyRSSI_LPS(pDM_Odm);
+ } else
+ odm_DIG(pDM_Odm);
+
+ {
+ struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
+
+ odm_Adaptivity(pDM_Odm, pDM_DigTable->CurIGValue);
+ }
+ odm_CCKPacketDetectionThresh(pDM_Odm);
+
+ if (*(pDM_Odm->pbPowerSaving) == true)
+ return;
+
+
+ odm_RefreshRateAdaptiveMask(pDM_Odm);
+ odm_EdcaTurboCheck(pDM_Odm);
+ ODM_CfoTracking(pDM_Odm);
+
+ ODM_TXPowerTrackingCheck(pDM_Odm);
+
+ /* odm_EdcaTurboCheck(pDM_Odm); */
+
+ /* 2010.05.30 LukeLee: For CE platform, files in IC subfolders may not be included to be compiled, */
+ /* so compile flags must be left here to prevent from compile errors */
+ pDM_Odm->PhyDbgInfo.NumQryBeaconPkt = 0;
+}
+
+
+/* */
+/* Init /.. Fixed HW value. Only init time. */
+/* */
+void ODM_CmnInfoInit(struct dm_odm_t *pDM_Odm, enum odm_cmninfo_e CmnInfo, u32 Value)
+{
+ /* */
+ /* This section is used for init value */
+ /* */
+ switch (CmnInfo) {
+ /* */
+ /* Fixed ODM value. */
+ /* */
+ case ODM_CMNINFO_ABILITY:
+ pDM_Odm->SupportAbility = (u32)Value;
+ break;
+
+ case ODM_CMNINFO_PLATFORM:
+ pDM_Odm->SupportPlatform = (u8)Value;
+ break;
+
+ case ODM_CMNINFO_INTERFACE:
+ pDM_Odm->SupportInterface = (u8)Value;
+ break;
+
+ case ODM_CMNINFO_IC_TYPE:
+ pDM_Odm->SupportICType = Value;
+ break;
+
+ case ODM_CMNINFO_CUT_VER:
+ pDM_Odm->CutVersion = (u8)Value;
+ break;
+
+ case ODM_CMNINFO_FAB_VER:
+ pDM_Odm->FabVersion = (u8)Value;
+ break;
+
+ case ODM_CMNINFO_RFE_TYPE:
+ pDM_Odm->RFEType = (u8)Value;
+ break;
+
+ case ODM_CMNINFO_RF_ANTENNA_TYPE:
+ pDM_Odm->AntDivType = (u8)Value;
+ break;
+
+ case ODM_CMNINFO_PACKAGE_TYPE:
+ pDM_Odm->PackageType = (u8)Value;
+ break;
+
+ case ODM_CMNINFO_EXT_LNA:
+ pDM_Odm->ExtLNA = (u8)Value;
+ break;
+
+ case ODM_CMNINFO_EXT_PA:
+ pDM_Odm->ExtPA = (u8)Value;
+ break;
+
+ case ODM_CMNINFO_GPA:
+ pDM_Odm->TypeGPA = (enum odm_type_gpa_e)Value;
+ break;
+ case ODM_CMNINFO_APA:
+ pDM_Odm->TypeAPA = (enum odm_type_apa_e)Value;
+ break;
+ case ODM_CMNINFO_GLNA:
+ pDM_Odm->TypeGLNA = (enum odm_type_glna_e)Value;
+ break;
+ case ODM_CMNINFO_ALNA:
+ pDM_Odm->TypeALNA = (enum odm_type_alna_e)Value;
+ break;
+
+ case ODM_CMNINFO_EXT_TRSW:
+ pDM_Odm->ExtTRSW = (u8)Value;
+ break;
+ case ODM_CMNINFO_PATCH_ID:
+ pDM_Odm->PatchID = (u8)Value;
+ break;
+ case ODM_CMNINFO_BINHCT_TEST:
+ pDM_Odm->bInHctTest = (bool)Value;
+ break;
+ case ODM_CMNINFO_BWIFI_TEST:
+ pDM_Odm->bWIFITest = (bool)Value;
+ break;
+
+ case ODM_CMNINFO_SMART_CONCURRENT:
+ pDM_Odm->bDualMacSmartConcurrent = (bool)Value;
+ break;
+
+ /* To remove the compiler warning, must add an empty default statement to handle the other values. */
+ default:
+ /* do nothing */
+ break;
+ }
+
+}
+
+
+void ODM_CmnInfoHook(struct dm_odm_t *pDM_Odm, enum odm_cmninfo_e CmnInfo, void *pValue)
+{
+ /* */
+ /* Hook call by reference pointer. */
+ /* */
+ switch (CmnInfo) {
+ /* */
+ /* Dynamic call by reference pointer. */
+ /* */
+ case ODM_CMNINFO_MAC_PHY_MODE:
+ pDM_Odm->pMacPhyMode = pValue;
+ break;
+
+ case ODM_CMNINFO_TX_UNI:
+ pDM_Odm->pNumTxBytesUnicast = pValue;
+ break;
+
+ case ODM_CMNINFO_RX_UNI:
+ pDM_Odm->pNumRxBytesUnicast = pValue;
+ break;
+
+ case ODM_CMNINFO_WM_MODE:
+ pDM_Odm->pwirelessmode = pValue;
+ break;
+
+ case ODM_CMNINFO_SEC_CHNL_OFFSET:
+ pDM_Odm->pSecChOffset = pValue;
+ break;
+
+ case ODM_CMNINFO_SEC_MODE:
+ pDM_Odm->pSecurity = pValue;
+ break;
+
+ case ODM_CMNINFO_BW:
+ pDM_Odm->pBandWidth = pValue;
+ break;
+
+ case ODM_CMNINFO_CHNL:
+ pDM_Odm->pChannel = pValue;
+ break;
+
+ case ODM_CMNINFO_DMSP_GET_VALUE:
+ pDM_Odm->pbGetValueFromOtherMac = pValue;
+ break;
+
+ case ODM_CMNINFO_BUDDY_ADAPTOR:
+ pDM_Odm->pBuddyAdapter = pValue;
+ break;
+
+ case ODM_CMNINFO_DMSP_IS_MASTER:
+ pDM_Odm->pbMasterOfDMSP = pValue;
+ break;
+
+ case ODM_CMNINFO_SCAN:
+ pDM_Odm->pbScanInProcess = pValue;
+ break;
+
+ case ODM_CMNINFO_POWER_SAVING:
+ pDM_Odm->pbPowerSaving = pValue;
+ break;
+
+ case ODM_CMNINFO_ONE_PATH_CCA:
+ pDM_Odm->pOnePathCCA = pValue;
+ break;
+
+ case ODM_CMNINFO_DRV_STOP:
+ pDM_Odm->pbDriverStopped = pValue;
+ break;
+
+ case ODM_CMNINFO_PNP_IN:
+ pDM_Odm->pbDriverIsGoingToPnpSetPowerSleep = pValue;
+ break;
+
+ case ODM_CMNINFO_INIT_ON:
+ pDM_Odm->pinit_adpt_in_progress = pValue;
+ break;
+
+ case ODM_CMNINFO_ANT_TEST:
+ pDM_Odm->pAntennaTest = pValue;
+ break;
+
+ case ODM_CMNINFO_NET_CLOSED:
+ pDM_Odm->pbNet_closed = pValue;
+ break;
+
+ case ODM_CMNINFO_FORCED_RATE:
+ pDM_Odm->pForcedDataRate = pValue;
+ break;
+
+ case ODM_CMNINFO_FORCED_IGI_LB:
+ pDM_Odm->pu1ForcedIgiLb = pValue;
+ break;
+
+ case ODM_CMNINFO_MP_MODE:
+ pDM_Odm->mp_mode = pValue;
+ break;
+
+ /* case ODM_CMNINFO_RTSTA_AID: */
+ /* pDM_Odm->pAidMap = (u8 *)pValue; */
+ /* break; */
+
+ /* case ODM_CMNINFO_BT_COEXIST: */
+ /* pDM_Odm->BTCoexist = (bool *)pValue; */
+
+ /* case ODM_CMNINFO_STA_STATUS: */
+ /* pDM_Odm->pODM_StaInfo[] = (PSTA_INFO_T)pValue; */
+ /* break; */
+
+ /* case ODM_CMNINFO_PHY_STATUS: */
+ /* pDM_Odm->pPhyInfo = (ODM_PHY_INFO *)pValue; */
+ /* break; */
+
+ /* case ODM_CMNINFO_MAC_STATUS: */
+ /* pDM_Odm->pMacInfo = (struct odm_mac_status_info *)pValue; */
+ /* break; */
+ /* To remove the compiler warning, must add an empty default statement to handle the other values. */
+ default:
+ /* do nothing */
+ break;
+ }
+
+}
+
+
+void ODM_CmnInfoPtrArrayHook(
+ struct dm_odm_t *pDM_Odm,
+ enum odm_cmninfo_e CmnInfo,
+ u16 Index,
+ void *pValue
+)
+{
+ /* */
+ /* Hook call by reference pointer. */
+ /* */
+ switch (CmnInfo) {
+ /* */
+ /* Dynamic call by reference pointer. */
+ /* */
+ case ODM_CMNINFO_STA_STATUS:
+ pDM_Odm->pODM_StaInfo[Index] = (PSTA_INFO_T)pValue;
+ break;
+ /* To remove the compiler warning, must add an empty default statement to handle the other values. */
+ default:
+ /* do nothing */
+ break;
+ }
+
+}
+
+
+/* */
+/* Update Band/CHannel/.. The values are dynamic but non-per-packet. */
+/* */
+void ODM_CmnInfoUpdate(struct dm_odm_t *pDM_Odm, u32 CmnInfo, u64 Value)
+{
+ /* */
+ /* This init variable may be changed in run time. */
+ /* */
+ switch (CmnInfo) {
+ case ODM_CMNINFO_LINK_IN_PROGRESS:
+ pDM_Odm->bLinkInProcess = (bool)Value;
+ break;
+
+ case ODM_CMNINFO_ABILITY:
+ pDM_Odm->SupportAbility = (u32)Value;
+ break;
+
+ case ODM_CMNINFO_WIFI_DIRECT:
+ pDM_Odm->bWIFI_Direct = (bool)Value;
+ break;
+
+ case ODM_CMNINFO_WIFI_DISPLAY:
+ pDM_Odm->bWIFI_Display = (bool)Value;
+ break;
+
+ case ODM_CMNINFO_LINK:
+ pDM_Odm->bLinked = (bool)Value;
+ break;
+
+ case ODM_CMNINFO_STATION_STATE:
+ pDM_Odm->bsta_state = (bool)Value;
+ break;
+
+ case ODM_CMNINFO_RSSI_MIN:
+ pDM_Odm->RSSI_Min = (u8)Value;
+ break;
+
+ case ODM_CMNINFO_RA_THRESHOLD_HIGH:
+ pDM_Odm->RateAdaptive.HighRSSIThresh = (u8)Value;
+ break;
+
+ case ODM_CMNINFO_RA_THRESHOLD_LOW:
+ pDM_Odm->RateAdaptive.LowRSSIThresh = (u8)Value;
+ break;
+ /* The following is for BT HS mode and BT coexist mechanism. */
+ case ODM_CMNINFO_BT_ENABLED:
+ pDM_Odm->bBtEnabled = (bool)Value;
+ break;
+
+ case ODM_CMNINFO_BT_HS_CONNECT_PROCESS:
+ pDM_Odm->bBtConnectProcess = (bool)Value;
+ break;
+
+ case ODM_CMNINFO_BT_HS_RSSI:
+ pDM_Odm->btHsRssi = (u8)Value;
+ break;
+
+ case ODM_CMNINFO_BT_OPERATION:
+ pDM_Odm->bBtHsOperation = (bool)Value;
+ break;
+
+ case ODM_CMNINFO_BT_LIMITED_DIG:
+ pDM_Odm->bBtLimitedDig = (bool)Value;
+ break;
+
+ case ODM_CMNINFO_BT_DISABLE_EDCA:
+ pDM_Odm->bBtDisableEdcaTurbo = (bool)Value;
+ break;
+
+/*
+ case ODM_CMNINFO_OP_MODE:
+ pDM_Odm->OPMode = (u8)Value;
+ break;
+
+ case ODM_CMNINFO_WM_MODE:
+ pDM_Odm->WirelessMode = (u8)Value;
+ break;
+
+ case ODM_CMNINFO_SEC_CHNL_OFFSET:
+ pDM_Odm->SecChOffset = (u8)Value;
+ break;
+
+ case ODM_CMNINFO_SEC_MODE:
+ pDM_Odm->Security = (u8)Value;
+ break;
+
+ case ODM_CMNINFO_BW:
+ pDM_Odm->BandWidth = (u8)Value;
+ break;
+
+ case ODM_CMNINFO_CHNL:
+ pDM_Odm->Channel = (u8)Value;
+ break;
+*/
+ default:
+ /* do nothing */
+ break;
+ }
+
+
+}
+
+/* 3 ============================================================ */
+/* 3 DIG */
+/* 3 ============================================================ */
+/*-----------------------------------------------------------------------------
+ * Function: odm_DIGInit()
+ *
+ * Overview: Set DIG scheme init value.
+ *
+ * Input: NONE
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ *
+ * Revised History:
+ *When Who Remark
+ *
+ *---------------------------------------------------------------------------
+ */
+
+/* Remove DIG by yuchen */
+
+/* Remove DIG and FA check by Yu Chen */
+
+/* 3 ============================================================ */
+/* 3 BB Power Save */
+/* 3 ============================================================ */
+
+/* Remove BB power saving by Yuchen */
+
+/* 3 ============================================================ */
+/* 3 Dynamic Tx Power */
+/* 3 ============================================================ */
+
+/* Remove BY YuChen */
+
diff --git a/drivers/staging/rtl8723bs/hal/odm.h b/drivers/staging/rtl8723bs/hal/odm.h
new file mode 100644
index 000000000..fe9782d2d
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/odm.h
@@ -0,0 +1,1175 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+
+#ifndef __HALDMOUTSRC_H__
+#define __HALDMOUTSRC_H__
+
+#include "odm_EdcaTurboCheck.h"
+#include "odm_DIG.h"
+#include "odm_DynamicBBPowerSaving.h"
+#include "odm_DynamicTxPower.h"
+#include "odm_CfoTracking.h"
+
+#define TP_MODE 0
+#define RSSI_MODE 1
+#define TRAFFIC_LOW 0
+#define TRAFFIC_HIGH 1
+#define NONE 0
+
+/* 3 Tx Power Tracking */
+/* 3 ============================================================ */
+#define DPK_DELTA_MAPPING_NUM 13
+#define index_mapping_HP_NUM 15
+#define OFDM_TABLE_SIZE 43
+#define CCK_TABLE_SIZE 33
+#define TXSCALE_TABLE_SIZE 37
+#define TXPWR_TRACK_TABLE_SIZE 30
+#define DELTA_SWINGIDX_SIZE 30
+#define BAND_NUM 4
+
+/* 3 PSD Handler */
+/* 3 ============================================================ */
+
+#define AFH_PSD 1 /* 0:normal PSD scan, 1: only do 20 pts PSD */
+#define MODE_40M 0 /* 0:20M, 1:40M */
+#define PSD_TH2 3
+#define PSD_CHMIN 20 /* Minimum channel number for BT AFH */
+#define SIR_STEP_SIZE 3
+#define Smooth_Size_1 5
+#define Smooth_TH_1 3
+#define Smooth_Size_2 10
+#define Smooth_TH_2 4
+#define Smooth_Size_3 20
+#define Smooth_TH_3 4
+#define Smooth_Step_Size 5
+#define Adaptive_SIR 1
+#define PSD_RESCAN 4
+#define PSD_SCAN_INTERVAL 700 /* ms */
+
+/* 8723A High Power IGI Setting */
+#define DM_DIG_HIGH_PWR_IGI_LOWER_BOUND 0x22
+#define DM_DIG_Gmode_HIGH_PWR_IGI_LOWER_BOUND 0x28
+#define DM_DIG_HIGH_PWR_THRESHOLD 0x3a
+#define DM_DIG_LOW_PWR_THRESHOLD 0x14
+
+/* ANT Test */
+#define ANTTESTALL 0x00 /* Ant A or B will be Testing */
+#define ANTTESTA 0x01 /* Ant A will be Testing */
+#define ANTTESTB 0x02 /* Ant B will be testing */
+
+#define PS_MODE_ACTIVE 0x01
+
+/* for 8723A Ant Definition--2012--06--07 due to different IC may be different ANT define */
+#define MAIN_ANT 1 /* Ant A or Ant Main */
+#define AUX_ANT 2 /* AntB or Ant Aux */
+#define MAX_ANT 3 /* 3 for AP using */
+
+/* Antenna Diversity Type */
+#define SW_ANTDIV 0
+#define HW_ANTDIV 1
+/* structure and define */
+
+/* Remove DIG by Yuchen */
+
+/* Remoce BB power saving by Yuchn */
+
+/* Remove DIG by yuchen */
+
+struct dynamic_primary_CCA {
+ u8 PriCCA_flag;
+ u8 intf_flag;
+ u8 intf_type;
+ u8 DupRTS_flag;
+ u8 Monitor_flag;
+ u8 CH_offset;
+ u8 MF_state;
+};
+
+struct ra_t {
+ u8 firstconnect;
+};
+
+struct rxhp_t {
+ u8 RXHP_flag;
+ u8 PSD_func_trigger;
+ u8 PSD_bitmap_RXHP[80];
+ u8 Pre_IGI;
+ u8 Cur_IGI;
+ u8 Pre_pw_th;
+ u8 Cur_pw_th;
+ bool First_time_enter;
+ bool RXHP_enable;
+ u8 TP_Mode;
+ struct timer_list PSDTimer;
+};
+
+#define ASSOCIATE_ENTRY_NUM 32 /* Max size of AsocEntry[]. */
+#define ODM_ASSOCIATE_ENTRY_NUM ASSOCIATE_ENTRY_NUM
+
+/* This indicates two different the steps. */
+/* In SWAW_STEP_PEAK, driver needs to switch antenna and listen to the signal on the air. */
+/* In SWAW_STEP_DETERMINE, driver just compares the signal captured in SWAW_STEP_PEAK */
+/* with original RSSI to determine if it is necessary to switch antenna. */
+#define SWAW_STEP_PEAK 0
+#define SWAW_STEP_DETERMINE 1
+
+#define TP_MODE 0
+#define RSSI_MODE 1
+#define TRAFFIC_LOW 0
+#define TRAFFIC_HIGH 1
+#define TRAFFIC_UltraLOW 2
+
+struct swat_t { /* _SW_Antenna_Switch_ */
+ u8 Double_chk_flag;
+ u8 try_flag;
+ s32 PreRSSI;
+ u8 CurAntenna;
+ u8 PreAntenna;
+ u8 RSSI_Trying;
+ u8 TestMode;
+ u8 bTriggerAntennaSwitch;
+ u8 SelectAntennaMap;
+ u8 RSSI_target;
+ u8 reset_idx;
+ u16 Single_Ant_Counter;
+ u16 Dual_Ant_Counter;
+ u16 Aux_FailDetec_Counter;
+ u16 Retry_Counter;
+
+ /* Before link Antenna Switch check */
+ u8 SWAS_NoLink_State;
+ u32 SWAS_NoLink_BK_Reg860;
+ u32 SWAS_NoLink_BK_Reg92c;
+ u32 SWAS_NoLink_BK_Reg948;
+ bool ANTA_ON; /* To indicate Ant A is or not */
+ bool ANTB_ON; /* To indicate Ant B is on or not */
+ bool Pre_Aux_FailDetec;
+ bool RSSI_AntDect_bResult;
+ u8 Ant2G;
+
+ s32 RSSI_sum_A;
+ s32 RSSI_sum_B;
+ s32 RSSI_cnt_A;
+ s32 RSSI_cnt_B;
+
+ u64 lastTxOkCnt;
+ u64 lastRxOkCnt;
+ u64 TXByteCnt_A;
+ u64 TXByteCnt_B;
+ u64 RXByteCnt_A;
+ u64 RXByteCnt_B;
+ u8 TrafficLoad;
+ u8 Train_time;
+ u8 Train_time_flag;
+ struct timer_list SwAntennaSwitchTimer;
+ struct timer_list SwAntennaSwitchTimer_8723B;
+ u32 PktCnt_SWAntDivByCtrlFrame;
+ bool bSWAntDivByCtrlFrame;
+};
+
+/* Remove Edca by YuChen */
+
+
+struct odm_rate_adaptive {
+ u8 Type; /* DM_Type_ByFW/DM_Type_ByDriver */
+ u8 LdpcThres; /* if RSSI > LdpcThres => switch from LPDC to BCC */
+ bool bUseLdpc;
+ bool bLowerRtsRate;
+ u8 HighRSSIThresh; /* if RSSI > HighRSSIThresh => RATRState is DM_RATR_STA_HIGH */
+ u8 LowRSSIThresh; /* if RSSI <= LowRSSIThresh => RATRState is DM_RATR_STA_LOW */
+ u8 RATRState; /* Current RSSI level, DM_RATR_STA_HIGH/DM_RATR_STA_MIDDLE/DM_RATR_STA_LOW */
+
+};
+
+#define IQK_MAC_REG_NUM 4
+#define IQK_ADDA_REG_NUM 16
+#define IQK_BB_REG_NUM_MAX 10
+#define IQK_BB_REG_NUM 9
+#define HP_THERMAL_NUM 8
+
+#define AVG_THERMAL_NUM 8
+#define IQK_Matrix_REG_NUM 8
+#define IQK_Matrix_Settings_NUM 14 /* Channels_2_4G_NUM */
+
+#define DM_Type_ByFW 0
+#define DM_Type_ByDriver 1
+
+/* */
+/* Declare for common info */
+/* */
+#define MAX_PATH_NUM_92CS 2
+#define MAX_PATH_NUM_8188E 1
+#define MAX_PATH_NUM_8192E 2
+#define MAX_PATH_NUM_8723B 1
+#define MAX_PATH_NUM_8812A 2
+#define MAX_PATH_NUM_8821A 1
+#define MAX_PATH_NUM_8814A 4
+#define MAX_PATH_NUM_8822B 2
+
+#define IQK_THRESHOLD 8
+#define DPK_THRESHOLD 4
+
+struct odm_phy_info {
+ /*
+ * Be care, if you want to add any element, please insert it between
+ * rx_pwd_ball and signal_strength.
+ */
+ u8 rx_pwd_ba11;
+
+ u8 signal_quality; /* in 0-100 index. */
+ s8 rx_mimo_signal_quality[4]; /* per-path's EVM */
+ u8 rx_mimo_evm_dbm[4]; /* per-path's EVM dbm */
+
+ u8 rx_mimo_signal_strength[4]; /* in 0~100 index */
+
+ u16 cfo_short[4]; /* per-path's Cfo_short */
+ u16 cfo_tail[4]; /* per-path's Cfo_tail */
+
+ s8 rx_power; /* in dBm Translate from PWdB */
+
+ /*
+ * Real power in dBm for this packet, no beautification and
+ * aggregation. Keep this raw info to be used for the other procedures.
+ */
+ s8 recv_signal_power;
+ u8 bt_rx_rssi_percentage;
+ u8 signal_strength; /* in 0-100 index. */
+
+ s8 rx_pwr[4]; /* per-path's pwdb */
+
+ u8 rx_snr[4]; /* per-path's SNR */
+ u8 band_width;
+ u8 bt_coex_pwr_adjust;
+};
+
+struct odm_packet_info {
+ u8 data_rate;
+ u8 station_id;
+ bool bssid_match;
+ bool to_self;
+ bool is_beacon;
+};
+
+struct odm_phy_dbg_info {
+ /* ODM Write, debug info */
+ s8 RxSNRdB[4];
+ u32 NumQryPhyStatus;
+ u32 NumQryPhyStatusCCK;
+ u32 NumQryPhyStatusOFDM;
+ u8 NumQryBeaconPkt;
+ /* Others */
+ s32 RxEVM[4];
+
+};
+
+struct odm_mac_status_info {
+ u8 test;
+};
+
+/* */
+/* 2011/10/20 MH Define Common info enum for all team. */
+/* */
+enum odm_cmninfo_e {
+ /* Fixed value: */
+
+ /* HOOK BEFORE REG INIT----------- */
+ ODM_CMNINFO_PLATFORM = 0,
+ ODM_CMNINFO_ABILITY, /* ODM_ABILITY_E */
+ ODM_CMNINFO_INTERFACE, /* ODM_INTERFACE_E */
+ ODM_CMNINFO_IC_TYPE, /* ODM_IC_TYPE_E */
+ ODM_CMNINFO_CUT_VER, /* ODM_CUT_VERSION_E */
+ ODM_CMNINFO_FAB_VER, /* ODM_FAB_E */
+ ODM_CMNINFO_RFE_TYPE,
+ ODM_CMNINFO_PACKAGE_TYPE,
+ ODM_CMNINFO_EXT_LNA, /* true */
+ ODM_CMNINFO_EXT_PA,
+ ODM_CMNINFO_GPA,
+ ODM_CMNINFO_APA,
+ ODM_CMNINFO_GLNA,
+ ODM_CMNINFO_ALNA,
+ ODM_CMNINFO_EXT_TRSW,
+ ODM_CMNINFO_PATCH_ID, /* CUSTOMER ID */
+ ODM_CMNINFO_BINHCT_TEST,
+ ODM_CMNINFO_BWIFI_TEST,
+ ODM_CMNINFO_SMART_CONCURRENT,
+ /* HOOK BEFORE REG INIT----------- */
+
+ /* Dynamic value: */
+/* POINTER REFERENCE----------- */
+ ODM_CMNINFO_MAC_PHY_MODE, /* ODM_MAC_PHY_MODE_E */
+ ODM_CMNINFO_TX_UNI,
+ ODM_CMNINFO_RX_UNI,
+ ODM_CMNINFO_WM_MODE, /* ODM_WIRELESS_MODE_E */
+ ODM_CMNINFO_SEC_CHNL_OFFSET, /* ODM_SEC_CHNL_OFFSET_E */
+ ODM_CMNINFO_SEC_MODE, /* ODM_SECURITY_E */
+ ODM_CMNINFO_BW, /* ODM_BW_E */
+ ODM_CMNINFO_CHNL,
+ ODM_CMNINFO_FORCED_RATE,
+
+ ODM_CMNINFO_DMSP_GET_VALUE,
+ ODM_CMNINFO_BUDDY_ADAPTOR,
+ ODM_CMNINFO_DMSP_IS_MASTER,
+ ODM_CMNINFO_SCAN,
+ ODM_CMNINFO_POWER_SAVING,
+ ODM_CMNINFO_ONE_PATH_CCA, /* ODM_CCA_PATH_E */
+ ODM_CMNINFO_DRV_STOP,
+ ODM_CMNINFO_PNP_IN,
+ ODM_CMNINFO_INIT_ON,
+ ODM_CMNINFO_ANT_TEST,
+ ODM_CMNINFO_NET_CLOSED,
+ ODM_CMNINFO_MP_MODE,
+ /* ODM_CMNINFO_RTSTA_AID, For win driver only? */
+ ODM_CMNINFO_FORCED_IGI_LB,
+ ODM_CMNINFO_IS1ANTENNA,
+ ODM_CMNINFO_RFDEFAULTPATH,
+/* POINTER REFERENCE----------- */
+
+/* CALL BY VALUE------------- */
+ ODM_CMNINFO_WIFI_DIRECT,
+ ODM_CMNINFO_WIFI_DISPLAY,
+ ODM_CMNINFO_LINK_IN_PROGRESS,
+ ODM_CMNINFO_LINK,
+ ODM_CMNINFO_STATION_STATE,
+ ODM_CMNINFO_RSSI_MIN,
+ ODM_CMNINFO_DBG_COMP, /* u64 */
+ ODM_CMNINFO_DBG_LEVEL, /* u32 */
+ ODM_CMNINFO_RA_THRESHOLD_HIGH, /* u8 */
+ ODM_CMNINFO_RA_THRESHOLD_LOW, /* u8 */
+ ODM_CMNINFO_RF_ANTENNA_TYPE, /* u8 */
+ ODM_CMNINFO_BT_ENABLED,
+ ODM_CMNINFO_BT_HS_CONNECT_PROCESS,
+ ODM_CMNINFO_BT_HS_RSSI,
+ ODM_CMNINFO_BT_OPERATION,
+ ODM_CMNINFO_BT_LIMITED_DIG, /* Need to Limited Dig or not */
+ ODM_CMNINFO_BT_DISABLE_EDCA,
+/* CALL BY VALUE------------- */
+
+ /* Dynamic ptr array hook itms. */
+ ODM_CMNINFO_STA_STATUS,
+ ODM_CMNINFO_PHY_STATUS,
+ ODM_CMNINFO_MAC_STATUS,
+
+ ODM_CMNINFO_MAX,
+};
+
+/* 2011/10/20 MH Define ODM support ability. ODM_CMNINFO_ABILITY */
+enum { /* _ODM_Support_Ability_Definition */
+ /* */
+ /* BB ODM section BIT 0-15 */
+ /* */
+ ODM_BB_DIG = BIT0,
+ ODM_BB_RA_MASK = BIT1,
+ ODM_BB_DYNAMIC_TXPWR = BIT2,
+ ODM_BB_FA_CNT = BIT3,
+ ODM_BB_RSSI_MONITOR = BIT4,
+ ODM_BB_CCK_PD = BIT5,
+ ODM_BB_ANT_DIV = BIT6,
+ ODM_BB_PWR_SAVE = BIT7,
+ ODM_BB_PWR_TRAIN = BIT8,
+ ODM_BB_RATE_ADAPTIVE = BIT9,
+ ODM_BB_PATH_DIV = BIT10,
+ ODM_BB_PSD = BIT11,
+ ODM_BB_RXHP = BIT12,
+ ODM_BB_ADAPTIVITY = BIT13,
+ ODM_BB_CFO_TRACKING = BIT14,
+
+ /* MAC DM section BIT 16-23 */
+ ODM_MAC_EDCA_TURBO = BIT16,
+ ODM_MAC_EARLY_MODE = BIT17,
+
+ /* RF ODM section BIT 24-31 */
+ ODM_RF_TX_PWR_TRACK = BIT24,
+ ODM_RF_RX_GAIN_TRACK = BIT25,
+ ODM_RF_CALIBRATION = BIT26,
+};
+
+/* ODM_CMNINFO_INTERFACE */
+enum { /* tag_ODM_Support_Interface_Definition */
+ ODM_ITRF_SDIO = 0x4,
+ ODM_ITRF_ALL = 0x7,
+};
+
+/* ODM_CMNINFO_IC_TYPE */
+enum { /* tag_ODM_Support_IC_Type_Definition */
+ ODM_RTL8723B = BIT8,
+};
+
+/* ODM_CMNINFO_CUT_VER */
+enum { /* tag_ODM_Cut_Version_Definition */
+ ODM_CUT_A = 0,
+ ODM_CUT_B = 1,
+ ODM_CUT_C = 2,
+ ODM_CUT_D = 3,
+ ODM_CUT_E = 4,
+ ODM_CUT_F = 5,
+
+ ODM_CUT_I = 8,
+ ODM_CUT_J = 9,
+ ODM_CUT_K = 10,
+ ODM_CUT_TEST = 15,
+};
+
+/* ODM_CMNINFO_FAB_VER */
+enum { /* tag_ODM_Fab_Version_Definition */
+ ODM_TSMC = 0,
+ ODM_UMC = 1,
+};
+
+/* */
+/* For example 1T2R (A+AB = BIT0|BIT4|BIT5) */
+/* */
+enum { /* tag_ODM_RF_Type_Definition */
+ ODM_1T1R = 0,
+ ODM_1T2R = 1,
+ ODM_2T2R = 2,
+ ODM_2T3R = 3,
+ ODM_2T4R = 4,
+ ODM_3T3R = 5,
+ ODM_3T4R = 6,
+ ODM_4T4R = 7,
+};
+
+/* */
+/* ODM Dynamic common info value definition */
+/* */
+
+/* ODM_CMNINFO_WM_MODE */
+enum { /* tag_Wireless_Mode_Definition */
+ ODM_WM_UNKNOWN = 0x0,
+ ODM_WM_B = BIT0,
+ ODM_WM_G = BIT1,
+ ODM_WM_N24G = BIT3,
+ ODM_WM_AUTO = BIT5,
+};
+
+/* ODM_CMNINFO_BW */
+enum { /* tag_Bandwidth_Definition */
+ ODM_BW20M = 0,
+ ODM_BW40M = 1,
+};
+
+/* For AC-series IC, external PA & LNA can be individually added on 2.4G */
+
+enum odm_type_gpa_e { /* tag_ODM_TYPE_GPA_Definition */
+ TYPE_GPA0 = 0,
+ TYPE_GPA1 = BIT(1)|BIT(0)
+};
+
+enum odm_type_apa_e { /* tag_ODM_TYPE_APA_Definition */
+ TYPE_APA0 = 0,
+ TYPE_APA1 = BIT(1)|BIT(0)
+};
+
+enum odm_type_glna_e { /* tag_ODM_TYPE_GLNA_Definition */
+ TYPE_GLNA0 = 0,
+ TYPE_GLNA1 = BIT(2)|BIT(0),
+ TYPE_GLNA2 = BIT(3)|BIT(1),
+ TYPE_GLNA3 = BIT(3)|BIT(2)|BIT(1)|BIT(0)
+};
+
+enum odm_type_alna_e { /* tag_ODM_TYPE_ALNA_Definition */
+ TYPE_ALNA0 = 0,
+ TYPE_ALNA1 = BIT(2)|BIT(0),
+ TYPE_ALNA2 = BIT(3)|BIT(1),
+ TYPE_ALNA3 = BIT(3)|BIT(2)|BIT(1)|BIT(0)
+};
+
+struct iqk_matrix_regs_setting { /* _IQK_MATRIX_REGS_SETTING */
+ bool bIQKDone;
+ s32 Value[3][IQK_Matrix_REG_NUM];
+ bool bBWIqkResultSaved[3];
+};
+
+/* Remove PATHDIV_PARA struct to odm_PathDiv.h */
+
+struct odm_rf_cal_t { /* ODM_RF_Calibration_Structure */
+ /* for tx power tracking */
+
+ u32 RegA24; /* for TempCCK */
+ s32 RegE94;
+ s32 RegE9C;
+ s32 RegEB4;
+ s32 RegEBC;
+
+ u8 TXPowercount;
+ bool bTXPowerTrackingInit;
+ bool bTXPowerTracking;
+ u8 TxPowerTrackControl; /* for mp mode, turn off txpwrtracking as default */
+ u8 TM_Trigger;
+
+ u8 ThermalMeter[2]; /* ThermalMeter, index 0 for RFIC0, and 1 for RFIC1 */
+ u8 ThermalValue;
+ u8 ThermalValue_LCK;
+ u8 ThermalValue_IQK;
+ u8 ThermalValue_DPK;
+ u8 ThermalValue_AVG[AVG_THERMAL_NUM];
+ u8 ThermalValue_AVG_index;
+ u8 ThermalValue_RxGain;
+ u8 ThermalValue_Crystal;
+ u8 ThermalValue_DPKstore;
+ u8 ThermalValue_DPKtrack;
+ bool TxPowerTrackingInProgress;
+
+ bool bReloadtxpowerindex;
+ u8 bRfPiEnable;
+ u32 TXPowerTrackingCallbackCnt; /* cosa add for debug */
+
+ /* Tx power Tracking ------------------------- */
+ u8 bCCKinCH14;
+ u8 CCK_index;
+ u8 OFDM_index[MAX_RF_PATH];
+ s8 PowerIndexOffset[MAX_RF_PATH];
+ s8 DeltaPowerIndex[MAX_RF_PATH];
+ s8 DeltaPowerIndexLast[MAX_RF_PATH];
+ bool bTxPowerChanged;
+
+ u8 ThermalValue_HP[HP_THERMAL_NUM];
+ u8 ThermalValue_HP_index;
+ struct iqk_matrix_regs_setting IQKMatrixRegSetting[IQK_Matrix_Settings_NUM];
+ bool bNeedIQK;
+ bool bIQKInProgress;
+ u8 Delta_IQK;
+ u8 Delta_LCK;
+ s8 BBSwingDiff2G; /* Unit: dB */
+ u8 DeltaSwingTableIdx_2GCCKA_P[DELTA_SWINGIDX_SIZE];
+ u8 DeltaSwingTableIdx_2GCCKA_N[DELTA_SWINGIDX_SIZE];
+ u8 DeltaSwingTableIdx_2GCCKB_P[DELTA_SWINGIDX_SIZE];
+ u8 DeltaSwingTableIdx_2GCCKB_N[DELTA_SWINGIDX_SIZE];
+ u8 DeltaSwingTableIdx_2GA_P[DELTA_SWINGIDX_SIZE];
+ u8 DeltaSwingTableIdx_2GA_N[DELTA_SWINGIDX_SIZE];
+ u8 DeltaSwingTableIdx_2GB_P[DELTA_SWINGIDX_SIZE];
+ u8 DeltaSwingTableIdx_2GB_N[DELTA_SWINGIDX_SIZE];
+ u8 DeltaSwingTableIdx_2GA_P_8188E[DELTA_SWINGIDX_SIZE];
+ u8 DeltaSwingTableIdx_2GA_N_8188E[DELTA_SWINGIDX_SIZE];
+
+ /* */
+
+ /* for IQK */
+ u32 RegC04;
+ u32 Reg874;
+ u32 RegC08;
+ u32 RegB68;
+ u32 RegB6C;
+ u32 Reg870;
+ u32 Reg860;
+ u32 Reg864;
+
+ bool bIQKInitialized;
+ bool bLCKInProgress;
+ bool bAntennaDetected;
+ u32 ADDA_backup[IQK_ADDA_REG_NUM];
+ u32 IQK_MAC_backup[IQK_MAC_REG_NUM];
+ u32 IQK_BB_backup_recover[9];
+ u32 IQK_BB_backup[IQK_BB_REG_NUM];
+ u32 TxIQC_8723B[2][3][2]; /* { {S1: 0xc94, 0xc80, 0xc4c} , {S0: 0xc9c, 0xc88, 0xc4c}} */
+ u32 RxIQC_8723B[2][2][2]; /* { {S1: 0xc14, 0xca0} , {S0: 0xc14, 0xca0}} */
+
+ /* for APK */
+ u32 APKoutput[2][2]; /* path A/B; output1_1a/output1_2a */
+ u8 bAPKdone;
+ u8 bAPKThermalMeterIgnore;
+
+ /* DPK */
+ bool bDPKFail;
+ u8 bDPdone;
+ u8 bDPPathAOK;
+ u8 bDPPathBOK;
+
+ u32 TxLOK[2];
+
+};
+/* */
+/* ODM Dynamic common info value definition */
+/* */
+
+struct fat_t { /* _FAST_ANTENNA_TRAINNING_ */
+ u8 Bssid[6];
+ u8 antsel_rx_keep_0;
+ u8 antsel_rx_keep_1;
+ u8 antsel_rx_keep_2;
+ u8 antsel_rx_keep_3;
+ u32 antSumRSSI[7];
+ u32 antRSSIcnt[7];
+ u32 antAveRSSI[7];
+ u8 FAT_State;
+ u32 TrainIdx;
+ u8 antsel_a[ODM_ASSOCIATE_ENTRY_NUM];
+ u8 antsel_b[ODM_ASSOCIATE_ENTRY_NUM];
+ u8 antsel_c[ODM_ASSOCIATE_ENTRY_NUM];
+ u32 MainAnt_Sum[ODM_ASSOCIATE_ENTRY_NUM];
+ u32 AuxAnt_Sum[ODM_ASSOCIATE_ENTRY_NUM];
+ u32 MainAnt_Cnt[ODM_ASSOCIATE_ENTRY_NUM];
+ u32 AuxAnt_Cnt[ODM_ASSOCIATE_ENTRY_NUM];
+ u8 RxIdleAnt;
+ bool bBecomeLinked;
+ u32 MinMaxRSSI;
+ u8 idx_AntDiv_counter_2G;
+ u32 CCK_counter_main;
+ u32 CCK_counter_aux;
+ u32 OFDM_counter_main;
+ u32 OFDM_counter_aux;
+
+ u32 CCK_CtrlFrame_Cnt_main;
+ u32 CCK_CtrlFrame_Cnt_aux;
+ u32 OFDM_CtrlFrame_Cnt_main;
+ u32 OFDM_CtrlFrame_Cnt_aux;
+ u32 MainAnt_CtrlFrame_Sum;
+ u32 AuxAnt_CtrlFrame_Sum;
+ u32 MainAnt_CtrlFrame_Cnt;
+ u32 AuxAnt_CtrlFrame_Cnt;
+
+};
+
+enum {
+ NO_ANTDIV = 0xFF,
+ CG_TRX_HW_ANTDIV = 0x01,
+ CGCS_RX_HW_ANTDIV = 0x02,
+ FIXED_HW_ANTDIV = 0x03,
+ CG_TRX_SMART_ANTDIV = 0x04,
+ CGCS_RX_SW_ANTDIV = 0x05,
+ S0S1_SW_ANTDIV = 0x06 /* 8723B intrnal switch S0 S1 */
+};
+
+struct pathdiv_t { /* _ODM_PATH_DIVERSITY_ */
+ u8 RespTxPath;
+ u8 PathSel[ODM_ASSOCIATE_ENTRY_NUM];
+ u32 PathA_Sum[ODM_ASSOCIATE_ENTRY_NUM];
+ u32 PathB_Sum[ODM_ASSOCIATE_ENTRY_NUM];
+ u32 PathA_Cnt[ODM_ASSOCIATE_ENTRY_NUM];
+ u32 PathB_Cnt[ODM_ASSOCIATE_ENTRY_NUM];
+};
+
+enum phy_reg_pg_type { /* _BASEBAND_CONFIG_PHY_REG_PG_VALUE_TYPE */
+ PHY_REG_PG_RELATIVE_VALUE = 0,
+ PHY_REG_PG_EXACT_VALUE = 1
+};
+
+/* */
+/* Antenna detection information from single tone mechanism, added by Roger, 2012.11.27. */
+/* */
+struct ant_detected_info {
+ bool bAntDetected;
+ u32 dBForAntA;
+ u32 dBForAntB;
+ u32 dBForAntO;
+};
+
+/* */
+/* 2011/09/22 MH Copy from SD4 defined structure. We use to support PHY DM integration. */
+/* */
+struct dm_odm_t { /* DM_Out_Source_Dynamic_Mechanism_Structure */
+ /* struct timer_list FastAntTrainingTimer; */
+ /* */
+ /* Add for different team use temporarily */
+ /* */
+ struct adapter *Adapter; /* For CE/NIC team */
+ /* WHen you use Adapter or priv pointer, you must make sure the pointer is ready. */
+ bool odm_ready;
+
+ enum phy_reg_pg_type PhyRegPgValueType;
+ u8 PhyRegPgVersion;
+
+ u32 NumQryPhyStatusAll; /* CCK + OFDM */
+ u32 LastNumQryPhyStatusAll;
+ u32 RxPWDBAve;
+ bool MPDIG_2G; /* off MPDIG */
+ u8 Times_2G;
+
+/* ODM HANDLE, DRIVER NEEDS NOT TO HOOK------ */
+ bool bCckHighPower;
+ u8 RFPathRxEnable; /* ODM_CMNINFO_RFPATH_ENABLE */
+ u8 ControlChannel;
+/* ODM HANDLE, DRIVER NEEDS NOT TO HOOK------ */
+
+/* REMOVED COMMON INFO---------- */
+ /* u8 PseudoMacPhyMode; */
+ /* bool *BTCoexist; */
+ /* bool PseudoBtCoexist; */
+ /* u8 OPMode; */
+ /* bool bAPMode; */
+ /* bool bClientMode; */
+ /* bool bAdHocMode; */
+ /* bool bSlaveOfDMSP; */
+/* REMOVED COMMON INFO---------- */
+
+/* 1 COMMON INFORMATION */
+
+ /* */
+ /* Init Value */
+ /* */
+/* HOOK BEFORE REG INIT----------- */
+ /* ODM Platform info AP/ADSL/CE/MP = 1/2/3/4 */
+ u8 SupportPlatform;
+ /* ODM Support Ability DIG/RATR/TX_PWR_TRACK/... = 1/2/3/... */
+ u32 SupportAbility;
+ /* ODM PCIE/USB/SDIO = 1/2/3 */
+ u8 SupportInterface;
+ /* ODM composite or independent. Bit oriented/ 92C+92D+ .... or any other type = 1/2/3/... */
+ u32 SupportICType;
+ /* Cut Version TestChip/A-cut/B-cut... = 0/1/2/3/... */
+ u8 CutVersion;
+ /* Fab Version TSMC/UMC = 0/1 */
+ u8 FabVersion;
+ /* RF Type 4T4R/3T3R/2T2R/1T2R/1T1R/... */
+ u8 RFEType;
+ /* Board Type Normal/HighPower/MiniCard/SLIM/Combo/... = 0/1/2/3/4/... */
+ u8 BoardType;
+ u8 PackageType;
+ u8 TypeGLNA;
+ u8 TypeGPA;
+ u8 TypeALNA;
+ u8 TypeAPA;
+ /* with external LNA NO/Yes = 0/1 */
+ u8 ExtLNA;
+ /* with external PA NO/Yes = 0/1 */
+ u8 ExtPA;
+ /* with external TRSW NO/Yes = 0/1 */
+ u8 ExtTRSW;
+ u8 PatchID; /* Customer ID */
+ bool bInHctTest;
+ bool bWIFITest;
+
+ bool bDualMacSmartConcurrent;
+ u32 BK_SupportAbility;
+ u8 AntDivType;
+/* HOOK BEFORE REG INIT----------- */
+
+ /* */
+ /* Dynamic Value */
+ /* */
+/* POINTER REFERENCE----------- */
+
+ u8 u8_temp;
+ bool bool_temp;
+ struct adapter *adapter_temp;
+
+ /* MAC PHY Mode SMSP/DMSP/DMDP = 0/1/2 */
+ u8 *pMacPhyMode;
+ /* TX Unicast byte count */
+ u64 *pNumTxBytesUnicast;
+ /* RX Unicast byte count */
+ u64 *pNumRxBytesUnicast;
+ /* Wireless mode B/G/A/N = BIT0/BIT1/BIT2/BIT3 */
+ u8 *pwirelessmode; /* ODM_WIRELESS_MODE_E */
+ /* Secondary channel offset don't_care/below/above = 0/1/2 */
+ u8 *pSecChOffset;
+ /* Security mode Open/WEP/AES/TKIP = 0/1/2/3 */
+ u8 *pSecurity;
+ /* BW info 20M/40M/80M = 0/1/2 */
+ u8 *pBandWidth;
+ /* Central channel location Ch1/Ch2/.... */
+ u8 *pChannel; /* central channel number */
+ bool DPK_Done;
+ /* Common info for 92D DMSP */
+
+ bool *pbGetValueFromOtherMac;
+ struct adapter **pBuddyAdapter;
+ bool *pbMasterOfDMSP; /* MAC0: master, MAC1: slave */
+ /* Common info for Status */
+ bool *pbScanInProcess;
+ bool *pbPowerSaving;
+ /* CCA Path 2-path/path-A/path-B = 0/1/2; using ODM_CCA_PATH_E. */
+ u8 *pOnePathCCA;
+ /* pMgntInfo->AntennaTest */
+ u8 *pAntennaTest;
+ bool *pbNet_closed;
+ u8 *mp_mode;
+ /* u8 *pAidMap; */
+ u8 *pu1ForcedIgiLb;
+/* For 8723B IQK----------- */
+ bool *pIs1Antenna;
+ u8 *pRFDefaultPath;
+ /* 0:S1, 1:S0 */
+
+/* POINTER REFERENCE----------- */
+ u16 *pForcedDataRate;
+/* CALL BY VALUE------------- */
+ bool bLinkInProcess;
+ bool bWIFI_Direct;
+ bool bWIFI_Display;
+ bool bLinked;
+
+ bool bsta_state;
+ u8 RSSI_Min;
+ u8 InterfaceIndex; /* Add for 92D dual MAC: 0--Mac0 1--Mac1 */
+ bool bOneEntryOnly;
+ /* Common info for BTDM */
+ bool bBtEnabled; /* BT is disabled */
+ bool bBtConnectProcess; /* BT HS is under connection progress. */
+ u8 btHsRssi; /* BT HS mode wifi rssi value. */
+ bool bBtHsOperation; /* BT HS mode is under progress */
+ bool bBtDisableEdcaTurbo; /* Under some condition, don't enable the EDCA Turbo */
+ bool bBtLimitedDig; /* BT is busy. */
+/* CALL BY VALUE------------- */
+ u8 RSSI_A;
+ u8 RSSI_B;
+ u64 RSSI_TRSW;
+ u64 RSSI_TRSW_H;
+ u64 RSSI_TRSW_L;
+ u64 RSSI_TRSW_iso;
+
+ u8 RxRate;
+ bool bNoisyState;
+ u8 TxRate;
+ u8 LinkedInterval;
+ u8 preChannel;
+ u32 TxagcOffsetValueA;
+ bool IsTxagcOffsetPositiveA;
+ u32 TxagcOffsetValueB;
+ bool IsTxagcOffsetPositiveB;
+ u64 lastTxOkCnt;
+ u64 lastRxOkCnt;
+ u32 BbSwingOffsetA;
+ bool IsBbSwingOffsetPositiveA;
+ u32 BbSwingOffsetB;
+ bool IsBbSwingOffsetPositiveB;
+ s8 TH_L2H_ini;
+ s8 TH_EDCCA_HL_diff;
+ s8 IGI_Base;
+ u8 IGI_target;
+ bool ForceEDCCA;
+ u8 AdapEn_RSSI;
+ s8 Force_TH_H;
+ s8 Force_TH_L;
+ u8 IGI_LowerBound;
+ u8 antdiv_rssi;
+ u8 AntType;
+ u8 pre_AntType;
+ u8 antdiv_period;
+ u8 antdiv_select;
+ u8 NdpaPeriod;
+ bool H2C_RARpt_connect;
+
+ /* add by Yu Cehn for adaptivtiy */
+ bool adaptivity_flag;
+ bool NHM_disable;
+ bool TxHangFlg;
+ bool Carrier_Sense_enable;
+ u8 tolerance_cnt;
+ u64 NHMCurTxOkcnt;
+ u64 NHMCurRxOkcnt;
+ u64 NHMLastTxOkcnt;
+ u64 NHMLastRxOkcnt;
+ u8 txEdcca1;
+ u8 txEdcca0;
+ s8 H2L_lb;
+ s8 L2H_lb;
+ u8 Adaptivity_IGI_upper;
+ u8 NHM_cnt_0;
+
+ /* */
+ /* 2 Define STA info. */
+ /* _ODM_STA_INFO */
+ /* 2012/01/12 MH For MP, we need to reduce one array pointer for default port.?? */
+ PSTA_INFO_T pODM_StaInfo[ODM_ASSOCIATE_ENTRY_NUM];
+
+ /* */
+ /* 2012/02/14 MH Add to share 88E ra with other SW team. */
+ /* We need to colelct all support abilit to a proper area. */
+ /* */
+ bool RaSupport88E;
+
+ /* Define ........... */
+
+ /* Latest packet phy info (ODM write) */
+ struct odm_phy_dbg_info PhyDbgInfo;
+ /* PHY_INFO_88E PhyInfo; */
+
+ /* Latest packet phy info (ODM write) */
+ struct odm_mac_status_info *pMacInfo;
+ /* MAC_INFO_88E MacInfo; */
+
+ /* Different Team independt structure?? */
+
+ /* */
+ /* TX_RTP_CMN TX_retrpo; */
+ /* TX_RTP_88E TX_retrpo; */
+ /* TX_RTP_8195 TX_retrpo; */
+
+ /* */
+ /* ODM Structure */
+ /* */
+ struct fat_t DM_FatTable;
+ struct dig_t DM_DigTable;
+ struct ps_t DM_PSTable;
+ struct dynamic_primary_CCA DM_PriCCA;
+ struct rxhp_t dM_RXHP_Table;
+ struct ra_t DM_RA_Table;
+ struct false_ALARM_STATISTICS FalseAlmCnt;
+ struct false_ALARM_STATISTICS FlaseAlmCntBuddyAdapter;
+ struct swat_t DM_SWAT_Table;
+ bool RSSI_test;
+ struct cfo_tracking DM_CfoTrack;
+
+ struct edca_t DM_EDCA_Table;
+ u32 WMMEDCA_BE;
+ struct pathdiv_t DM_PathDiv;
+ /* Copy from SD4 structure */
+ /* */
+ /* ================================================== */
+ /* */
+
+ /* common */
+ /* u8 DM_Type; */
+ /* u8 PSD_Report_RXHP[80]; Add By Gary */
+ /* u8 PSD_func_flag; Add By Gary */
+ /* for DIG */
+ /* u8 bDMInitialGainEnable; */
+ /* u8 binitialized; for dm_initial_gain_Multi_STA use. */
+ /* for Antenna diversity */
+ /* u8 AntDivCfg; 0:OFF , 1:ON, 2:by efuse */
+ /* PSTA_INFO_T RSSI_target; */
+
+ bool *pbDriverStopped;
+ bool *pbDriverIsGoingToPnpSetPowerSleep;
+ bool *pinit_adpt_in_progress;
+
+ /* PSD */
+ bool bUserAssignLevel;
+ struct timer_list PSDTimer;
+ u8 RSSI_BT; /* come from BT */
+ bool bPSDinProcess;
+ bool bPSDactive;
+ bool bDMInitialGainEnable;
+
+ /* MPT DIG */
+ struct timer_list MPT_DIGTimer;
+
+ /* for rate adaptive, in fact, 88c/92c fw will handle this */
+ u8 bUseRAMask;
+
+ struct odm_rate_adaptive RateAdaptive;
+
+ struct ant_detected_info AntDetectedInfo; /* Antenna detected information for RSSI tool */
+
+ struct odm_rf_cal_t RFCalibrateInfo;
+
+ /* */
+ /* TX power tracking */
+ /* */
+ u8 BbSwingIdxOfdm[MAX_RF_PATH];
+ u8 BbSwingIdxOfdmCurrent;
+ u8 BbSwingIdxOfdmBase[MAX_RF_PATH];
+ bool BbSwingFlagOfdm;
+ u8 BbSwingIdxCck;
+ u8 BbSwingIdxCckCurrent;
+ u8 BbSwingIdxCckBase;
+ u8 DefaultOfdmIndex;
+ u8 DefaultCckIndex;
+ bool BbSwingFlagCck;
+
+ s8 Absolute_OFDMSwingIdx[MAX_RF_PATH];
+ s8 Remnant_OFDMSwingIdx[MAX_RF_PATH];
+ s8 Remnant_CCKSwingIdx;
+ s8 Modify_TxAGC_Value; /* Remnat compensate value at TxAGC */
+ bool Modify_TxAGC_Flag_PathA;
+ bool Modify_TxAGC_Flag_PathB;
+ bool Modify_TxAGC_Flag_PathC;
+ bool Modify_TxAGC_Flag_PathD;
+ bool Modify_TxAGC_Flag_PathA_CCK;
+
+ s8 KfreeOffset[MAX_RF_PATH];
+ /* */
+ /* ODM system resource. */
+ /* */
+
+ /* ODM relative time. */
+ struct timer_list PathDivSwitchTimer;
+ /* 2011.09.27 add for Path Diversity */
+ struct timer_list CCKPathDiversityTimer;
+ struct timer_list FastAntTrainingTimer;
+
+ /* ODM relative workitem. */
+
+ #if (BEAMFORMING_SUPPORT == 1)
+ RT_BEAMFORMING_INFO BeamformingInfo;
+ #endif
+};
+
+ enum odm_rf_content {
+ odm_radioa_txt = 0x1000,
+ odm_radiob_txt = 0x1001,
+ odm_radioc_txt = 0x1002,
+ odm_radiod_txt = 0x1003
+};
+
+enum ODM_BB_Config_Type {
+ CONFIG_BB_PHY_REG,
+ CONFIG_BB_AGC_TAB,
+ CONFIG_BB_AGC_TAB_2G,
+ CONFIG_BB_PHY_REG_PG,
+ CONFIG_BB_PHY_REG_MP,
+ CONFIG_BB_AGC_TAB_DIFF,
+};
+
+enum ODM_RF_Config_Type {
+ CONFIG_RF_RADIO,
+ CONFIG_RF_TXPWR_LMT,
+};
+
+enum ODM_FW_Config_Type {
+ CONFIG_FW_NIC,
+ CONFIG_FW_NIC_2,
+ CONFIG_FW_AP,
+ CONFIG_FW_WoWLAN,
+ CONFIG_FW_WoWLAN_2,
+ CONFIG_FW_AP_WoWLAN,
+ CONFIG_FW_BT,
+};
+
+#ifdef REMOVE_PACK
+#pragma pack()
+#endif
+
+/* include "odm_function.h" */
+
+/* 3 =========================================================== */
+/* 3 DIG */
+/* 3 =========================================================== */
+
+/* Remove DIG by Yuchen */
+
+/* 3 =========================================================== */
+/* 3 AGC RX High Power Mode */
+/* 3 =========================================================== */
+#define LNA_Low_Gain_1 0x64
+#define LNA_Low_Gain_2 0x5A
+#define LNA_Low_Gain_3 0x58
+
+#define FA_RXHP_TH1 5000
+#define FA_RXHP_TH2 1500
+#define FA_RXHP_TH3 800
+#define FA_RXHP_TH4 600
+#define FA_RXHP_TH5 500
+
+/* 3 =========================================================== */
+/* 3 EDCA */
+/* 3 =========================================================== */
+
+/* 3 =========================================================== */
+/* 3 Dynamic Tx Power */
+/* 3 =========================================================== */
+/* Dynamic Tx Power Control Threshold */
+
+/* 3 =========================================================== */
+/* 3 Rate Adaptive */
+/* 3 =========================================================== */
+#define DM_RATR_STA_INIT 0
+#define DM_RATR_STA_HIGH 1
+#define DM_RATR_STA_MIDDLE 2
+#define DM_RATR_STA_LOW 3
+
+/* 3 =========================================================== */
+/* 3 BB Power Save */
+/* 3 =========================================================== */
+
+enum { /* tag_1R_CCA_Type_Definition */
+ CCA_1R = 0,
+ CCA_2R = 1,
+ CCA_MAX = 2,
+};
+
+enum { /* tag_RF_Type_Definition */
+ RF_Save = 0,
+ RF_Normal = 1,
+ RF_MAX = 2,
+};
+
+/* Maximal number of antenna detection mechanism needs to perform, added by Roger, 2011.12.28. */
+#define MAX_ANTENNA_DETECTION_CNT 10
+
+/* */
+/* Extern Global Variables. */
+/* */
+extern u32 OFDMSwingTable[OFDM_TABLE_SIZE];
+extern u8 CCKSwingTable_Ch1_Ch13[CCK_TABLE_SIZE][8];
+extern u8 CCKSwingTable_Ch14[CCK_TABLE_SIZE][8];
+
+extern u32 OFDMSwingTable_New[OFDM_TABLE_SIZE];
+extern u8 CCKSwingTable_Ch1_Ch13_New[CCK_TABLE_SIZE][8];
+extern u8 CCKSwingTable_Ch14_New[CCK_TABLE_SIZE][8];
+
+extern u32 TxScalingTable_Jaguar[TXSCALE_TABLE_SIZE];
+
+/* */
+/* check Sta pointer valid or not */
+/* */
+#define IS_STA_VALID(pSta) (pSta)
+/* 20100514 Joseph: Add definition for antenna switching test after link. */
+/* This indicates two different the steps. */
+/* In SWAW_STEP_PEAK, driver needs to switch antenna and listen to the signal on the air. */
+/* In SWAW_STEP_DETERMINE, driver just compares the signal captured in SWAW_STEP_PEAK */
+/* with original RSSI to determine if it is necessary to switch antenna. */
+#define SWAW_STEP_PEAK 0
+#define SWAW_STEP_DETERMINE 1
+
+/* Remove BB power saving by Yuchen */
+
+#define dm_CheckTXPowerTracking ODM_TXPowerTrackingCheck
+void ODM_TXPowerTrackingCheck(struct dm_odm_t *pDM_Odm);
+
+bool ODM_RAStateCheck(
+ struct dm_odm_t *pDM_Odm,
+ s32 RSSI,
+ bool bForceUpdate,
+ u8 *pRATRState
+);
+
+#define dm_SWAW_RSSI_Check ODM_SwAntDivChkPerPktRssi
+void ODM_SwAntDivChkPerPktRssi(
+ struct dm_odm_t *pDM_Odm,
+ u8 StationID,
+ struct odm_phy_info *pPhyInfo
+);
+
+u32 ODM_Get_Rate_Bitmap(
+ struct dm_odm_t *pDM_Odm,
+ u32 macid,
+ u32 ra_mask,
+ u8 rssi_level
+);
+
+#if (BEAMFORMING_SUPPORT == 1)
+BEAMFORMING_CAP Beamforming_GetEntryBeamCapByMacId(PMGNT_INFO pMgntInfo, u8 MacId);
+#endif
+
+void odm_TXPowerTrackingInit(struct dm_odm_t *pDM_Odm);
+
+void ODM_DMInit(struct dm_odm_t *pDM_Odm);
+
+void ODM_DMWatchdog(struct dm_odm_t *pDM_Odm); /* For common use in the future */
+
+void ODM_CmnInfoInit(struct dm_odm_t *pDM_Odm, enum odm_cmninfo_e CmnInfo, u32 Value);
+
+void ODM_CmnInfoHook(struct dm_odm_t *pDM_Odm, enum odm_cmninfo_e CmnInfo, void *pValue);
+
+void ODM_CmnInfoPtrArrayHook(
+ struct dm_odm_t *pDM_Odm,
+ enum odm_cmninfo_e CmnInfo,
+ u16 Index,
+ void *pValue
+);
+
+void ODM_CmnInfoUpdate(struct dm_odm_t *pDM_Odm, u32 CmnInfo, u64 Value);
+
+void ODM_InitAllTimers(struct dm_odm_t *pDM_Odm);
+
+void ODM_CancelAllTimers(struct dm_odm_t *pDM_Odm);
+
+void ODM_ReleaseAllTimers(struct dm_odm_t *pDM_Odm);
+
+void ODM_AntselStatistics_88C(
+ struct dm_odm_t *pDM_Odm,
+ u8 MacId,
+ u32 PWDBAll,
+ bool isCCKrate
+);
+
+void ODM_DynamicARFBSelect(struct dm_odm_t *pDM_Odm, u8 rate, bool Collision_State);
+
+#endif
diff --git a/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c b/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c
new file mode 100644
index 000000000..928c58be6
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c
@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include "odm_precomp.h"
+
+static void odm_SetCrystalCap(void *pDM_VOID, u8 CrystalCap)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+ struct cfo_tracking *pCfoTrack = &pDM_Odm->DM_CfoTrack;
+
+ if (pCfoTrack->CrystalCap == CrystalCap)
+ return;
+
+ pCfoTrack->CrystalCap = CrystalCap;
+
+ /* 0x2C[23:18] = 0x2C[17:12] = CrystalCap */
+ CrystalCap = CrystalCap & 0x3F;
+ PHY_SetBBReg(
+ pDM_Odm->Adapter,
+ REG_MAC_PHY_CTRL,
+ 0x00FFF000,
+ (CrystalCap | (CrystalCap << 6))
+ );
+}
+
+static u8 odm_GetDefaultCrytaltalCap(void *pDM_VOID)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+
+ return pHalData->CrystalCap & 0x3f;
+}
+
+static void odm_SetATCStatus(void *pDM_VOID, bool ATCStatus)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+ struct cfo_tracking *pCfoTrack = &pDM_Odm->DM_CfoTrack;
+
+ if (pCfoTrack->bATCStatus == ATCStatus)
+ return;
+
+ PHY_SetBBReg(
+ pDM_Odm->Adapter,
+ ODM_REG(BB_ATC, pDM_Odm),
+ ODM_BIT(BB_ATC, pDM_Odm),
+ ATCStatus
+ );
+ pCfoTrack->bATCStatus = ATCStatus;
+}
+
+static bool odm_GetATCStatus(void *pDM_VOID)
+{
+ bool ATCStatus;
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+
+ ATCStatus = (bool)PHY_QueryBBReg(
+ pDM_Odm->Adapter,
+ ODM_REG(BB_ATC, pDM_Odm),
+ ODM_BIT(BB_ATC, pDM_Odm)
+ );
+ return ATCStatus;
+}
+
+void ODM_CfoTrackingReset(void *pDM_VOID)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+ struct cfo_tracking *pCfoTrack = &pDM_Odm->DM_CfoTrack;
+
+ pCfoTrack->DefXCap = odm_GetDefaultCrytaltalCap(pDM_Odm);
+ pCfoTrack->bAdjust = true;
+
+ odm_SetCrystalCap(pDM_Odm, pCfoTrack->DefXCap);
+ odm_SetATCStatus(pDM_Odm, true);
+}
+
+void ODM_CfoTrackingInit(void *pDM_VOID)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+ struct cfo_tracking *pCfoTrack = &pDM_Odm->DM_CfoTrack;
+
+ pCfoTrack->DefXCap =
+ pCfoTrack->CrystalCap = odm_GetDefaultCrytaltalCap(pDM_Odm);
+ pCfoTrack->bATCStatus = odm_GetATCStatus(pDM_Odm);
+ pCfoTrack->bAdjust = true;
+}
+
+void ODM_CfoTracking(void *pDM_VOID)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+ struct cfo_tracking *pCfoTrack = &pDM_Odm->DM_CfoTrack;
+ int CFO_kHz_A, CFO_ave = 0;
+ int CFO_ave_diff;
+ int CrystalCap = (int)pCfoTrack->CrystalCap;
+ u8 Adjust_Xtal = 1;
+
+ /* 4 Support ability */
+ if (!(pDM_Odm->SupportAbility & ODM_BB_CFO_TRACKING)) {
+ return;
+ }
+
+ if (!pDM_Odm->bLinked || !pDM_Odm->bOneEntryOnly) {
+ /* 4 No link or more than one entry */
+ ODM_CfoTrackingReset(pDM_Odm);
+ } else {
+ /* 3 1. CFO Tracking */
+ /* 4 1.1 No new packet */
+ if (pCfoTrack->packetCount == pCfoTrack->packetCount_pre) {
+ return;
+ }
+ pCfoTrack->packetCount_pre = pCfoTrack->packetCount;
+
+ /* 4 1.2 Calculate CFO */
+ CFO_kHz_A = (int)(pCfoTrack->CFO_tail[0] * 3125) / 1280;
+
+ CFO_ave = CFO_kHz_A;
+
+ /* 4 1.3 Avoid abnormal large CFO */
+ CFO_ave_diff =
+ (pCfoTrack->CFO_ave_pre >= CFO_ave) ?
+ (pCfoTrack->CFO_ave_pre-CFO_ave) :
+ (CFO_ave-pCfoTrack->CFO_ave_pre);
+
+ if (
+ CFO_ave_diff > 20 &&
+ pCfoTrack->largeCFOHit == 0 &&
+ !pCfoTrack->bAdjust
+ ) {
+ pCfoTrack->largeCFOHit = 1;
+ return;
+ } else
+ pCfoTrack->largeCFOHit = 0;
+ pCfoTrack->CFO_ave_pre = CFO_ave;
+
+ /* 4 1.4 Dynamic Xtal threshold */
+ if (pCfoTrack->bAdjust == false) {
+ if (CFO_ave > CFO_TH_XTAL_HIGH || CFO_ave < (-CFO_TH_XTAL_HIGH))
+ pCfoTrack->bAdjust = true;
+ } else {
+ if (CFO_ave < CFO_TH_XTAL_LOW && CFO_ave > (-CFO_TH_XTAL_LOW))
+ pCfoTrack->bAdjust = false;
+ }
+
+ /* 4 1.5 BT case: Disable CFO tracking */
+ if (pDM_Odm->bBtEnabled) {
+ pCfoTrack->bAdjust = false;
+ odm_SetCrystalCap(pDM_Odm, pCfoTrack->DefXCap);
+ }
+
+ /* 4 1.6 Big jump */
+ if (pCfoTrack->bAdjust) {
+ if (CFO_ave > CFO_TH_XTAL_LOW)
+ Adjust_Xtal = Adjust_Xtal+((CFO_ave-CFO_TH_XTAL_LOW)>>2);
+ else if (CFO_ave < (-CFO_TH_XTAL_LOW))
+ Adjust_Xtal = Adjust_Xtal+((CFO_TH_XTAL_LOW-CFO_ave)>>2);
+ }
+
+ /* 4 1.7 Adjust Crystal Cap. */
+ if (pCfoTrack->bAdjust) {
+ if (CFO_ave > CFO_TH_XTAL_LOW)
+ CrystalCap = CrystalCap + Adjust_Xtal;
+ else if (CFO_ave < (-CFO_TH_XTAL_LOW))
+ CrystalCap = CrystalCap - Adjust_Xtal;
+
+ if (CrystalCap > 0x3f)
+ CrystalCap = 0x3f;
+ else if (CrystalCap < 0)
+ CrystalCap = 0;
+
+ odm_SetCrystalCap(pDM_Odm, (u8)CrystalCap);
+ }
+
+ /* 3 2. Dynamic ATC switch */
+ if (CFO_ave < CFO_TH_ATC && CFO_ave > -CFO_TH_ATC) {
+ odm_SetATCStatus(pDM_Odm, false);
+ } else {
+ odm_SetATCStatus(pDM_Odm, true);
+ }
+ }
+}
+
+void odm_parsing_cfo(void *dm_void, void *pkt_info_void, s8 *cfotail)
+{
+ struct dm_odm_t *dm_odm = (struct dm_odm_t *)dm_void;
+ struct odm_packet_info *pkt_info = pkt_info_void;
+ struct cfo_tracking *cfo_track = &dm_odm->DM_CfoTrack;
+ u8 i;
+
+ if (!(dm_odm->SupportAbility & ODM_BB_CFO_TRACKING))
+ return;
+
+ if (pkt_info->station_id != 0) {
+ /*
+ * 3 Update CFO report for path-A & path-B
+ * Only paht-A and path-B have CFO tail and short CFO
+ */
+ for (i = RF_PATH_A; i <= RF_PATH_B; i++)
+ cfo_track->CFO_tail[i] = (int)cfotail[i];
+
+ /* 3 Update packet counter */
+ if (cfo_track->packetCount == 0xffffffff)
+ cfo_track->packetCount = 0;
+ else
+ cfo_track->packetCount++;
+ }
+}
diff --git a/drivers/staging/rtl8723bs/hal/odm_CfoTracking.h b/drivers/staging/rtl8723bs/hal/odm_CfoTracking.h
new file mode 100644
index 000000000..8fa6d9ec5
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/odm_CfoTracking.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#ifndef __ODMCFOTRACK_H__
+#define __ODMCFOTRACK_H__
+
+#define CFO_TH_XTAL_HIGH 20 /* kHz */
+#define CFO_TH_XTAL_LOW 10 /* kHz */
+#define CFO_TH_ATC 80 /* kHz */
+
+struct cfo_tracking {
+ bool bATCStatus;
+ bool largeCFOHit;
+ bool bAdjust;
+ u8 CrystalCap;
+ u8 DefXCap;
+ int CFO_tail[2];
+ int CFO_ave_pre;
+ u32 packetCount;
+ u32 packetCount_pre;
+
+ bool bForceXtalCap;
+ bool bReset;
+};
+
+void ODM_CfoTrackingReset(void *pDM_VOID
+);
+
+void ODM_CfoTrackingInit(void *pDM_VOID);
+
+void ODM_CfoTracking(void *pDM_VOID);
+
+void odm_parsing_cfo(void *pDM_VOID, void *pPktinfo_VOID, s8 *pcfotail);
+
+#endif
diff --git a/drivers/staging/rtl8723bs/hal/odm_DIG.c b/drivers/staging/rtl8723bs/hal/odm_DIG.c
new file mode 100644
index 000000000..07edf74cc
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/odm_DIG.c
@@ -0,0 +1,825 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include "odm_precomp.h"
+
+void odm_NHMCounterStatisticsInit(void *pDM_VOID)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+
+ /* PHY parameters initialize for n series */
+ rtw_write16(pDM_Odm->Adapter, ODM_REG_NHM_TIMER_11N+2, 0x2710); /* 0x894[31:16]= 0x2710 Time duration for NHM unit: 4us, 0x2710 =40ms */
+ /* rtw_write16(pDM_Odm->Adapter, ODM_REG_NHM_TIMER_11N+2, 0x4e20); 0x894[31:16]= 0x4e20 Time duration for NHM unit: 4us, 0x4e20 =80ms */
+ rtw_write16(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N+2, 0xffff); /* 0x890[31:16]= 0xffff th_9, th_10 */
+ /* rtw_write32(pDM_Odm->Adapter, ODM_REG_NHM_TH3_TO_TH0_11N, 0xffffff5c); 0x898 = 0xffffff5c th_3, th_2, th_1, th_0 */
+ rtw_write32(pDM_Odm->Adapter, ODM_REG_NHM_TH3_TO_TH0_11N, 0xffffff52); /* 0x898 = 0xffffff52 th_3, th_2, th_1, th_0 */
+ rtw_write32(pDM_Odm->Adapter, ODM_REG_NHM_TH7_TO_TH4_11N, 0xffffffff); /* 0x89c = 0xffffffff th_7, th_6, th_5, th_4 */
+ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_FPGA0_IQK_11N, bMaskByte0, 0xff); /* 0xe28[7:0]= 0xff th_8 */
+ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N, BIT10|BIT9|BIT8, 0x7); /* 0x890[9:8]=3 enable CCX */
+ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_OFDM_FA_RSTC_11N, BIT7, 0x1); /* 0xc0c[7]= 1 max power among all RX ants */
+}
+
+void odm_NHMCounterStatistics(void *pDM_VOID)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+
+ /* Get NHM report */
+ odm_GetNHMCounterStatistics(pDM_Odm);
+
+ /* Reset NHM counter */
+ odm_NHMCounterStatisticsReset(pDM_Odm);
+}
+
+void odm_GetNHMCounterStatistics(void *pDM_VOID)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+ u32 value32 = 0;
+
+ value32 = PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG_NHM_CNT_11N, bMaskDWord);
+
+ pDM_Odm->NHM_cnt_0 = (u8)(value32 & bMaskByte0);
+}
+
+void odm_NHMCounterStatisticsReset(void *pDM_VOID)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+
+ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N, BIT1, 0);
+ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N, BIT1, 1);
+}
+
+void odm_NHMBBInit(void *pDM_VOID)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+
+ pDM_Odm->adaptivity_flag = 0;
+ pDM_Odm->tolerance_cnt = 3;
+ pDM_Odm->NHMLastTxOkcnt = 0;
+ pDM_Odm->NHMLastRxOkcnt = 0;
+ pDM_Odm->NHMCurTxOkcnt = 0;
+ pDM_Odm->NHMCurRxOkcnt = 0;
+}
+
+/* */
+void odm_NHMBB(void *pDM_VOID)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+ /* u8 test_status; */
+ /* struct false_ALARM_STATISTICS *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt; */
+
+ pDM_Odm->NHMCurTxOkcnt =
+ *(pDM_Odm->pNumTxBytesUnicast)-pDM_Odm->NHMLastTxOkcnt;
+ pDM_Odm->NHMCurRxOkcnt =
+ *(pDM_Odm->pNumRxBytesUnicast)-pDM_Odm->NHMLastRxOkcnt;
+ pDM_Odm->NHMLastTxOkcnt =
+ *(pDM_Odm->pNumTxBytesUnicast);
+ pDM_Odm->NHMLastRxOkcnt =
+ *(pDM_Odm->pNumRxBytesUnicast);
+
+
+ if ((pDM_Odm->NHMCurTxOkcnt) + 1 > (u64)(pDM_Odm->NHMCurRxOkcnt<<2) + 1) { /* Tx > 4*Rx possible for adaptivity test */
+ if (pDM_Odm->NHM_cnt_0 >= 190 || pDM_Odm->adaptivity_flag == true) {
+ /* Enable EDCCA since it is possible running Adaptivity testing */
+ /* test_status = 1; */
+ pDM_Odm->adaptivity_flag = true;
+ pDM_Odm->tolerance_cnt = 0;
+ } else {
+ if (pDM_Odm->tolerance_cnt < 3)
+ pDM_Odm->tolerance_cnt = pDM_Odm->tolerance_cnt + 1;
+ else
+ pDM_Odm->tolerance_cnt = 4;
+ /* test_status = 5; */
+ if (pDM_Odm->tolerance_cnt > 3) {
+ /* test_status = 3; */
+ pDM_Odm->adaptivity_flag = false;
+ }
+ }
+ } else { /* TX<RX */
+ if (pDM_Odm->adaptivity_flag == true && pDM_Odm->NHM_cnt_0 <= 200) {
+ /* test_status = 2; */
+ pDM_Odm->tolerance_cnt = 0;
+ } else {
+ if (pDM_Odm->tolerance_cnt < 3)
+ pDM_Odm->tolerance_cnt = pDM_Odm->tolerance_cnt + 1;
+ else
+ pDM_Odm->tolerance_cnt = 4;
+ /* test_status = 5; */
+ if (pDM_Odm->tolerance_cnt > 3) {
+ /* test_status = 4; */
+ pDM_Odm->adaptivity_flag = false;
+ }
+ }
+ }
+}
+
+void odm_SearchPwdBLowerBound(void *pDM_VOID, u8 IGI_target)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+ u32 value32 = 0;
+ u8 cnt, IGI;
+ bool bAdjust = true;
+ s8 TH_L2H_dmc, TH_H2L_dmc;
+ s8 Diff;
+
+ IGI = 0x50; /* find H2L, L2H lower bound */
+ ODM_Write_DIG(pDM_Odm, IGI);
+
+
+ Diff = IGI_target-(s8)IGI;
+ TH_L2H_dmc = pDM_Odm->TH_L2H_ini + Diff;
+ if (TH_L2H_dmc > 10)
+ TH_L2H_dmc = 10;
+ TH_H2L_dmc = TH_L2H_dmc - pDM_Odm->TH_EDCCA_HL_diff;
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte0, (u8)TH_L2H_dmc);
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte2, (u8)TH_H2L_dmc);
+
+ mdelay(5);
+
+ while (bAdjust) {
+ for (cnt = 0; cnt < 20; cnt++) {
+ value32 = PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG_RPT_11N, bMaskDWord);
+
+ if (value32 & BIT30)
+ pDM_Odm->txEdcca1 = pDM_Odm->txEdcca1 + 1;
+ else if (value32 & BIT29)
+ pDM_Odm->txEdcca1 = pDM_Odm->txEdcca1 + 1;
+ else
+ pDM_Odm->txEdcca0 = pDM_Odm->txEdcca0 + 1;
+ }
+
+ if (pDM_Odm->txEdcca1 > 5) {
+ IGI = IGI-1;
+ TH_L2H_dmc = TH_L2H_dmc + 1;
+ if (TH_L2H_dmc > 10)
+ TH_L2H_dmc = 10;
+ TH_H2L_dmc = TH_L2H_dmc - pDM_Odm->TH_EDCCA_HL_diff;
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte0, (u8)TH_L2H_dmc);
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte2, (u8)TH_H2L_dmc);
+
+ pDM_Odm->TxHangFlg = true;
+ pDM_Odm->txEdcca1 = 0;
+ pDM_Odm->txEdcca0 = 0;
+
+ if (TH_L2H_dmc == 10) {
+ bAdjust = false;
+ pDM_Odm->TxHangFlg = false;
+ pDM_Odm->txEdcca1 = 0;
+ pDM_Odm->txEdcca0 = 0;
+ pDM_Odm->H2L_lb = TH_H2L_dmc;
+ pDM_Odm->L2H_lb = TH_L2H_dmc;
+ pDM_Odm->Adaptivity_IGI_upper = IGI;
+ }
+ } else {
+ bAdjust = false;
+ pDM_Odm->TxHangFlg = false;
+ pDM_Odm->txEdcca1 = 0;
+ pDM_Odm->txEdcca0 = 0;
+ pDM_Odm->H2L_lb = TH_H2L_dmc;
+ pDM_Odm->L2H_lb = TH_L2H_dmc;
+ pDM_Odm->Adaptivity_IGI_upper = IGI;
+ }
+ }
+}
+
+void odm_AdaptivityInit(void *pDM_VOID)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+
+ if (pDM_Odm->Carrier_Sense_enable == false)
+ pDM_Odm->TH_L2H_ini = 0xf7; /* -7 */
+ else
+ pDM_Odm->TH_L2H_ini = 0xa;
+
+ pDM_Odm->AdapEn_RSSI = 20;
+ pDM_Odm->TH_EDCCA_HL_diff = 7;
+
+ pDM_Odm->IGI_Base = 0x32;
+ pDM_Odm->IGI_target = 0x1c;
+ pDM_Odm->ForceEDCCA = 0;
+ pDM_Odm->NHM_disable = false;
+ pDM_Odm->TxHangFlg = true;
+ pDM_Odm->txEdcca0 = 0;
+ pDM_Odm->txEdcca1 = 0;
+ pDM_Odm->H2L_lb = 0;
+ pDM_Odm->L2H_lb = 0;
+ pDM_Odm->Adaptivity_IGI_upper = 0;
+ odm_NHMBBInit(pDM_Odm);
+
+ PHY_SetBBReg(pDM_Odm->Adapter, REG_RD_CTRL, BIT11, 1); /* stop counting if EDCCA is asserted */
+}
+
+
+void odm_Adaptivity(void *pDM_VOID, u8 IGI)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+ s8 TH_L2H_dmc, TH_H2L_dmc;
+ s8 Diff, IGI_target;
+ bool EDCCA_State = false;
+
+ if (!(pDM_Odm->SupportAbility & ODM_BB_ADAPTIVITY)) {
+ return;
+ }
+
+ if (*pDM_Odm->pBandWidth == ODM_BW20M) /* CHANNEL_WIDTH_20 */
+ IGI_target = pDM_Odm->IGI_Base;
+ else if (*pDM_Odm->pBandWidth == ODM_BW40M)
+ IGI_target = pDM_Odm->IGI_Base + 2;
+ else
+ IGI_target = pDM_Odm->IGI_Base;
+ pDM_Odm->IGI_target = (u8) IGI_target;
+
+ /* Search pwdB lower bound */
+ if (pDM_Odm->TxHangFlg == true) {
+ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_DBG_RPT_11N, bMaskDWord, 0x208);
+ odm_SearchPwdBLowerBound(pDM_Odm, pDM_Odm->IGI_target);
+ }
+
+ if ((!pDM_Odm->bLinked) || (*pDM_Odm->pChannel > 149)) { /* Band4 doesn't need adaptivity */
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte0, 0x7f);
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte2, 0x7f);
+ return;
+ }
+
+ if (!pDM_Odm->ForceEDCCA) {
+ if (pDM_Odm->RSSI_Min > pDM_Odm->AdapEn_RSSI)
+ EDCCA_State = true;
+ else if (pDM_Odm->RSSI_Min < (pDM_Odm->AdapEn_RSSI - 5))
+ EDCCA_State = false;
+ } else
+ EDCCA_State = true;
+
+ if (
+ pDM_Odm->bLinked &&
+ pDM_Odm->Carrier_Sense_enable == false &&
+ pDM_Odm->NHM_disable == false &&
+ pDM_Odm->TxHangFlg == false
+ )
+ odm_NHMBB(pDM_Odm);
+
+ if (EDCCA_State) {
+ Diff = IGI_target-(s8)IGI;
+ TH_L2H_dmc = pDM_Odm->TH_L2H_ini + Diff;
+ if (TH_L2H_dmc > 10)
+ TH_L2H_dmc = 10;
+
+ TH_H2L_dmc = TH_L2H_dmc - pDM_Odm->TH_EDCCA_HL_diff;
+
+ /* replace lower bound to prevent EDCCA always equal */
+ if (TH_H2L_dmc < pDM_Odm->H2L_lb)
+ TH_H2L_dmc = pDM_Odm->H2L_lb;
+ if (TH_L2H_dmc < pDM_Odm->L2H_lb)
+ TH_L2H_dmc = pDM_Odm->L2H_lb;
+ } else {
+ TH_L2H_dmc = 0x7f;
+ TH_H2L_dmc = 0x7f;
+ }
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte0, (u8)TH_L2H_dmc);
+ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte2, (u8)TH_H2L_dmc);
+}
+
+void ODM_Write_DIG(void *pDM_VOID, u8 CurrentIGI)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+ struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
+
+ if (pDM_DigTable->bStopDIG) {
+ return;
+ }
+
+ if (pDM_DigTable->CurIGValue != CurrentIGI) {
+ /* 1 Check initial gain by upper bound */
+ if (!pDM_DigTable->bPSDInProgress) {
+ if (CurrentIGI > pDM_DigTable->rx_gain_range_max) {
+ CurrentIGI = pDM_DigTable->rx_gain_range_max;
+ }
+
+ }
+
+ /* 1 Set IGI value */
+ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm), CurrentIGI);
+
+ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG(IGI_B, pDM_Odm), ODM_BIT(IGI, pDM_Odm), CurrentIGI);
+
+ pDM_DigTable->CurIGValue = CurrentIGI;
+ }
+
+}
+
+bool odm_DigAbort(void *pDM_VOID)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+
+ /* SupportAbility */
+ if (!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT)) {
+ return true;
+ }
+
+ /* SupportAbility */
+ if (!(pDM_Odm->SupportAbility & ODM_BB_DIG)) {
+ return true;
+ }
+
+ /* ScanInProcess */
+ if (*(pDM_Odm->pbScanInProcess)) {
+ return true;
+ }
+
+ /* add by Neil Chen to avoid PSD is processing */
+ if (pDM_Odm->bDMInitialGainEnable == false) {
+ return true;
+ }
+
+ return false;
+}
+
+void odm_DIGInit(void *pDM_VOID)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+ struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
+
+ pDM_DigTable->bStopDIG = false;
+ pDM_DigTable->bPSDInProgress = false;
+ pDM_DigTable->CurIGValue = (u8) PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm));
+ pDM_DigTable->RssiLowThresh = DM_DIG_THRESH_LOW;
+ pDM_DigTable->RssiHighThresh = DM_DIG_THRESH_HIGH;
+ pDM_DigTable->FALowThresh = DMfalseALARM_THRESH_LOW;
+ pDM_DigTable->FAHighThresh = DMfalseALARM_THRESH_HIGH;
+ pDM_DigTable->BackoffVal = DM_DIG_BACKOFF_DEFAULT;
+ pDM_DigTable->BackoffVal_range_max = DM_DIG_BACKOFF_MAX;
+ pDM_DigTable->BackoffVal_range_min = DM_DIG_BACKOFF_MIN;
+ pDM_DigTable->PreCCK_CCAThres = 0xFF;
+ pDM_DigTable->CurCCK_CCAThres = 0x83;
+ pDM_DigTable->ForbiddenIGI = DM_DIG_MIN_NIC;
+ pDM_DigTable->LargeFAHit = 0;
+ pDM_DigTable->Recover_cnt = 0;
+ pDM_DigTable->bMediaConnect_0 = false;
+ pDM_DigTable->bMediaConnect_1 = false;
+
+ /* To Initialize pDM_Odm->bDMInitialGainEnable == false to avoid DIG error */
+ pDM_Odm->bDMInitialGainEnable = true;
+
+ pDM_DigTable->DIG_Dynamic_MIN_0 = DM_DIG_MIN_NIC;
+ pDM_DigTable->DIG_Dynamic_MIN_1 = DM_DIG_MIN_NIC;
+
+ /* To Initi BT30 IGI */
+ pDM_DigTable->BT30_CurIGI = 0x32;
+
+ pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC;
+ pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC;
+
+}
+
+
+void odm_DIG(void *pDM_VOID)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+
+ /* Common parameters */
+ struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
+ struct false_ALARM_STATISTICS *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt;
+ bool FirstConnect, FirstDisConnect;
+ u8 DIG_MaxOfMin, DIG_Dynamic_MIN;
+ u8 dm_dig_max, dm_dig_min;
+ u8 CurrentIGI = pDM_DigTable->CurIGValue;
+ u8 offset;
+ u32 dm_FA_thres[3];
+ u8 Adap_IGI_Upper = 0;
+ u32 TxTp = 0, RxTp = 0;
+ bool bDFSBand = false;
+ bool bPerformance = true, bFirstTpTarget = false, bFirstCoverage = false;
+
+ if (odm_DigAbort(pDM_Odm))
+ return;
+
+ if (pDM_Odm->adaptivity_flag == true)
+ Adap_IGI_Upper = pDM_Odm->Adaptivity_IGI_upper;
+
+
+ /* 1 Update status */
+ DIG_Dynamic_MIN = pDM_DigTable->DIG_Dynamic_MIN_0;
+ FirstConnect = (pDM_Odm->bLinked) && (pDM_DigTable->bMediaConnect_0 == false);
+ FirstDisConnect = (!pDM_Odm->bLinked) && (pDM_DigTable->bMediaConnect_0 == true);
+
+ /* 1 Boundary Decision */
+ /* 2 For WIN\CE */
+ dm_dig_max = 0x5A;
+ dm_dig_min = DM_DIG_MIN_NIC;
+ DIG_MaxOfMin = DM_DIG_MAX_AP;
+
+ /* 1 Adjust boundary by RSSI */
+ if (pDM_Odm->bLinked && bPerformance) {
+ /* 2 Modify DIG upper bound */
+ /* 4 Modify DIG upper bound for 92E, 8723A\B, 8821 & 8812 BT */
+ if (pDM_Odm->bBtLimitedDig == 1) {
+ offset = 10;
+ } else
+ offset = 15;
+
+ if ((pDM_Odm->RSSI_Min + offset) > dm_dig_max)
+ pDM_DigTable->rx_gain_range_max = dm_dig_max;
+ else if ((pDM_Odm->RSSI_Min + offset) < dm_dig_min)
+ pDM_DigTable->rx_gain_range_max = dm_dig_min;
+ else
+ pDM_DigTable->rx_gain_range_max = pDM_Odm->RSSI_Min + offset;
+
+ /* 2 Modify DIG lower bound */
+ /* if (pDM_Odm->bOneEntryOnly) */
+ {
+ if (pDM_Odm->RSSI_Min < dm_dig_min)
+ DIG_Dynamic_MIN = dm_dig_min;
+ else if (pDM_Odm->RSSI_Min > DIG_MaxOfMin)
+ DIG_Dynamic_MIN = DIG_MaxOfMin;
+ else
+ DIG_Dynamic_MIN = pDM_Odm->RSSI_Min;
+ }
+ } else {
+ pDM_DigTable->rx_gain_range_max = dm_dig_max;
+ DIG_Dynamic_MIN = dm_dig_min;
+ }
+
+ /* 1 Force Lower Bound for AntDiv */
+ if (pDM_Odm->bLinked && !pDM_Odm->bOneEntryOnly) {
+ if (pDM_Odm->SupportAbility & ODM_BB_ANT_DIV) {
+ if (
+ pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV ||
+ pDM_Odm->AntDivType == CG_TRX_SMART_ANTDIV ||
+ pDM_Odm->AntDivType == S0S1_SW_ANTDIV
+ ) {
+ if (pDM_DigTable->AntDiv_RSSI_max > DIG_MaxOfMin)
+ DIG_Dynamic_MIN = DIG_MaxOfMin;
+ else
+ DIG_Dynamic_MIN = (u8) pDM_DigTable->AntDiv_RSSI_max;
+ }
+ }
+ }
+
+ /* 1 Modify DIG lower bound, deal with abnormal case */
+ /* 2 Abnormal false alarm case */
+ if (FirstDisConnect) {
+ pDM_DigTable->rx_gain_range_min = DIG_Dynamic_MIN;
+ pDM_DigTable->ForbiddenIGI = DIG_Dynamic_MIN;
+ } else
+ pDM_DigTable->rx_gain_range_min =
+ odm_ForbiddenIGICheck(pDM_Odm, DIG_Dynamic_MIN, CurrentIGI);
+
+ if (pDM_Odm->bLinked && !FirstConnect) {
+ if (
+ (pDM_Odm->PhyDbgInfo.NumQryBeaconPkt < 5) &&
+ pDM_Odm->bsta_state
+ ) {
+ pDM_DigTable->rx_gain_range_min = dm_dig_min;
+ }
+ }
+
+ /* 2 Abnormal lower bound case */
+ if (pDM_DigTable->rx_gain_range_min > pDM_DigTable->rx_gain_range_max) {
+ pDM_DigTable->rx_gain_range_min = pDM_DigTable->rx_gain_range_max;
+ }
+
+
+ /* 1 False alarm threshold decision */
+ odm_FAThresholdCheck(pDM_Odm, bDFSBand, bPerformance, RxTp, TxTp, dm_FA_thres);
+
+ /* 1 Adjust initial gain by false alarm */
+ if (pDM_Odm->bLinked && bPerformance) {
+
+ if (bFirstTpTarget || FirstConnect) {
+ pDM_DigTable->LargeFAHit = 0;
+
+ if (pDM_Odm->RSSI_Min < DIG_MaxOfMin) {
+ if (CurrentIGI < pDM_Odm->RSSI_Min)
+ CurrentIGI = pDM_Odm->RSSI_Min;
+ } else {
+ if (CurrentIGI < DIG_MaxOfMin)
+ CurrentIGI = DIG_MaxOfMin;
+ }
+
+ } else {
+ if (pFalseAlmCnt->Cnt_all > dm_FA_thres[2])
+ CurrentIGI = CurrentIGI + 4;
+ else if (pFalseAlmCnt->Cnt_all > dm_FA_thres[1])
+ CurrentIGI = CurrentIGI + 2;
+ else if (pFalseAlmCnt->Cnt_all < dm_FA_thres[0])
+ CurrentIGI = CurrentIGI - 2;
+
+ if (
+ (pDM_Odm->PhyDbgInfo.NumQryBeaconPkt < 5) &&
+ (pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH1) &&
+ (pDM_Odm->bsta_state)
+ ) {
+ CurrentIGI = pDM_DigTable->rx_gain_range_min;
+ }
+ }
+ } else {
+
+ if (FirstDisConnect || bFirstCoverage) {
+ CurrentIGI = dm_dig_min;
+ } else {
+ if (pFalseAlmCnt->Cnt_all > dm_FA_thres[2])
+ CurrentIGI = CurrentIGI + 4;
+ else if (pFalseAlmCnt->Cnt_all > dm_FA_thres[1])
+ CurrentIGI = CurrentIGI + 2;
+ else if (pFalseAlmCnt->Cnt_all < dm_FA_thres[0])
+ CurrentIGI = CurrentIGI - 2;
+ }
+ }
+
+ /* 1 Check initial gain by upper/lower bound */
+ if (CurrentIGI < pDM_DigTable->rx_gain_range_min)
+ CurrentIGI = pDM_DigTable->rx_gain_range_min;
+
+ if (CurrentIGI > pDM_DigTable->rx_gain_range_max)
+ CurrentIGI = pDM_DigTable->rx_gain_range_max;
+
+ /* 1 Force upper bound and lower bound for adaptivity */
+ if (
+ pDM_Odm->SupportAbility & ODM_BB_ADAPTIVITY &&
+ pDM_Odm->adaptivity_flag == true
+ ) {
+ if (CurrentIGI > Adap_IGI_Upper)
+ CurrentIGI = Adap_IGI_Upper;
+
+ if (pDM_Odm->IGI_LowerBound != 0) {
+ if (CurrentIGI < pDM_Odm->IGI_LowerBound)
+ CurrentIGI = pDM_Odm->IGI_LowerBound;
+ }
+ }
+
+
+ /* 1 Update status */
+ if (pDM_Odm->bBtHsOperation) {
+ if (pDM_Odm->bLinked) {
+ if (pDM_DigTable->BT30_CurIGI > (CurrentIGI))
+ ODM_Write_DIG(pDM_Odm, CurrentIGI);
+ else
+ ODM_Write_DIG(pDM_Odm, pDM_DigTable->BT30_CurIGI);
+
+ pDM_DigTable->bMediaConnect_0 = pDM_Odm->bLinked;
+ pDM_DigTable->DIG_Dynamic_MIN_0 = DIG_Dynamic_MIN;
+ } else {
+ if (pDM_Odm->bLinkInProcess)
+ ODM_Write_DIG(pDM_Odm, 0x1c);
+ else if (pDM_Odm->bBtConnectProcess)
+ ODM_Write_DIG(pDM_Odm, 0x28);
+ else
+ ODM_Write_DIG(pDM_Odm, pDM_DigTable->BT30_CurIGI);/* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */
+ }
+ } else { /* BT is not using */
+ ODM_Write_DIG(pDM_Odm, CurrentIGI);/* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */
+ pDM_DigTable->bMediaConnect_0 = pDM_Odm->bLinked;
+ pDM_DigTable->DIG_Dynamic_MIN_0 = DIG_Dynamic_MIN;
+ }
+}
+
+void odm_DIGbyRSSI_LPS(void *pDM_VOID)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+ struct false_ALARM_STATISTICS *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt;
+
+ u8 RSSI_Lower = DM_DIG_MIN_NIC; /* 0x1E or 0x1C */
+ u8 CurrentIGI = pDM_Odm->RSSI_Min;
+
+ CurrentIGI = CurrentIGI+RSSI_OFFSET_DIG;
+
+ /* Using FW PS mode to make IGI */
+ /* Adjust by FA in LPS MODE */
+ if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH2_LPS)
+ CurrentIGI = CurrentIGI+4;
+ else if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH1_LPS)
+ CurrentIGI = CurrentIGI+2;
+ else if (pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH0_LPS)
+ CurrentIGI = CurrentIGI-2;
+
+
+ /* Lower bound checking */
+
+ /* RSSI Lower bound check */
+ if ((pDM_Odm->RSSI_Min-10) > DM_DIG_MIN_NIC)
+ RSSI_Lower = pDM_Odm->RSSI_Min-10;
+ else
+ RSSI_Lower = DM_DIG_MIN_NIC;
+
+ /* Upper and Lower Bound checking */
+ if (CurrentIGI > DM_DIG_MAX_NIC)
+ CurrentIGI = DM_DIG_MAX_NIC;
+ else if (CurrentIGI < RSSI_Lower)
+ CurrentIGI = RSSI_Lower;
+
+ ODM_Write_DIG(pDM_Odm, CurrentIGI);
+ /* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */
+}
+
+/* 3 ============================================================ */
+/* 3 FASLE ALARM CHECK */
+/* 3 ============================================================ */
+
+void odm_FalseAlarmCounterStatistics(void *pDM_VOID)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+ struct false_ALARM_STATISTICS *FalseAlmCnt = &pDM_Odm->FalseAlmCnt;
+ u32 ret_value;
+
+ if (!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT))
+ return;
+
+ /* hold ofdm counter */
+ /* hold page C counter */
+ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_OFDM_FA_HOLDC_11N, BIT31, 1);
+ /* hold page D counter */
+ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_OFDM_FA_RSTD_11N, BIT31, 1);
+
+ ret_value = PHY_QueryBBReg(
+ pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE1_11N, bMaskDWord
+ );
+ FalseAlmCnt->Cnt_Fast_Fsync = (ret_value&0xffff);
+ FalseAlmCnt->Cnt_SB_Search_fail = ((ret_value&0xffff0000)>>16);
+
+ ret_value = PHY_QueryBBReg(
+ pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE2_11N, bMaskDWord
+ );
+ FalseAlmCnt->Cnt_OFDM_CCA = (ret_value&0xffff);
+ FalseAlmCnt->Cnt_Parity_Fail = ((ret_value&0xffff0000)>>16);
+
+ ret_value = PHY_QueryBBReg(
+ pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE3_11N, bMaskDWord
+ );
+ FalseAlmCnt->Cnt_Rate_Illegal = (ret_value&0xffff);
+ FalseAlmCnt->Cnt_Crc8_fail = ((ret_value&0xffff0000)>>16);
+
+ ret_value = PHY_QueryBBReg(
+ pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE4_11N, bMaskDWord
+ );
+ FalseAlmCnt->Cnt_Mcs_fail = (ret_value&0xffff);
+
+ FalseAlmCnt->Cnt_Ofdm_fail =
+ FalseAlmCnt->Cnt_Parity_Fail +
+ FalseAlmCnt->Cnt_Rate_Illegal +
+ FalseAlmCnt->Cnt_Crc8_fail +
+ FalseAlmCnt->Cnt_Mcs_fail +
+ FalseAlmCnt->Cnt_Fast_Fsync +
+ FalseAlmCnt->Cnt_SB_Search_fail;
+
+ {
+ /* hold cck counter */
+ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_CCK_FA_RST_11N, BIT12, 1);
+ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_CCK_FA_RST_11N, BIT14, 1);
+
+ ret_value = PHY_QueryBBReg(
+ pDM_Odm->Adapter, ODM_REG_CCK_FA_LSB_11N, bMaskByte0
+ );
+ FalseAlmCnt->Cnt_Cck_fail = ret_value;
+
+ ret_value = PHY_QueryBBReg(
+ pDM_Odm->Adapter, ODM_REG_CCK_FA_MSB_11N, bMaskByte3
+ );
+ FalseAlmCnt->Cnt_Cck_fail += (ret_value&0xff)<<8;
+
+ ret_value = PHY_QueryBBReg(
+ pDM_Odm->Adapter, ODM_REG_CCK_CCA_CNT_11N, bMaskDWord
+ );
+ FalseAlmCnt->Cnt_CCK_CCA =
+ ((ret_value&0xFF)<<8) | ((ret_value&0xFF00)>>8);
+ }
+
+ FalseAlmCnt->Cnt_all = (
+ FalseAlmCnt->Cnt_Fast_Fsync +
+ FalseAlmCnt->Cnt_SB_Search_fail +
+ FalseAlmCnt->Cnt_Parity_Fail +
+ FalseAlmCnt->Cnt_Rate_Illegal +
+ FalseAlmCnt->Cnt_Crc8_fail +
+ FalseAlmCnt->Cnt_Mcs_fail +
+ FalseAlmCnt->Cnt_Cck_fail
+ );
+
+ FalseAlmCnt->Cnt_CCA_all =
+ FalseAlmCnt->Cnt_OFDM_CCA + FalseAlmCnt->Cnt_CCK_CCA;
+}
+
+
+void odm_FAThresholdCheck(
+ void *pDM_VOID,
+ bool bDFSBand,
+ bool bPerformance,
+ u32 RxTp,
+ u32 TxTp,
+ u32 *dm_FA_thres
+)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+
+ if (pDM_Odm->bLinked && (bPerformance || bDFSBand)) {
+ /* For NIC */
+ dm_FA_thres[0] = DM_DIG_FA_TH0;
+ dm_FA_thres[1] = DM_DIG_FA_TH1;
+ dm_FA_thres[2] = DM_DIG_FA_TH2;
+ } else {
+ dm_FA_thres[0] = 2000;
+ dm_FA_thres[1] = 4000;
+ dm_FA_thres[2] = 5000;
+ }
+}
+
+u8 odm_ForbiddenIGICheck(void *pDM_VOID, u8 DIG_Dynamic_MIN, u8 CurrentIGI)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+ struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
+ struct false_ALARM_STATISTICS *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt;
+ u8 rx_gain_range_min = pDM_DigTable->rx_gain_range_min;
+
+ if (pFalseAlmCnt->Cnt_all > 10000) {
+ if (pDM_DigTable->LargeFAHit != 3)
+ pDM_DigTable->LargeFAHit++;
+
+ /* if (pDM_DigTable->ForbiddenIGI < pDM_DigTable->CurIGValue) */
+ if (pDM_DigTable->ForbiddenIGI < CurrentIGI) {
+ pDM_DigTable->ForbiddenIGI = CurrentIGI;
+ /* pDM_DigTable->ForbiddenIGI = pDM_DigTable->CurIGValue; */
+ pDM_DigTable->LargeFAHit = 1;
+ }
+
+ if (pDM_DigTable->LargeFAHit >= 3) {
+ if ((pDM_DigTable->ForbiddenIGI + 2) > pDM_DigTable->rx_gain_range_max)
+ rx_gain_range_min = pDM_DigTable->rx_gain_range_max;
+ else
+ rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 2);
+ pDM_DigTable->Recover_cnt = 1800;
+ }
+ } else {
+ if (pDM_DigTable->Recover_cnt != 0) {
+ pDM_DigTable->Recover_cnt--;
+ } else {
+ if (pDM_DigTable->LargeFAHit < 3) {
+ if ((pDM_DigTable->ForbiddenIGI - 2) < DIG_Dynamic_MIN) { /* DM_DIG_MIN) */
+ pDM_DigTable->ForbiddenIGI = DIG_Dynamic_MIN; /* DM_DIG_MIN; */
+ rx_gain_range_min = DIG_Dynamic_MIN; /* DM_DIG_MIN; */
+ } else {
+ pDM_DigTable->ForbiddenIGI -= 2;
+ rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 2);
+ }
+ } else
+ pDM_DigTable->LargeFAHit = 0;
+ }
+ }
+
+ return rx_gain_range_min;
+
+}
+
+/* 3 ============================================================ */
+/* 3 CCK Packet Detect Threshold */
+/* 3 ============================================================ */
+
+void odm_CCKPacketDetectionThresh(void *pDM_VOID)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+ struct false_ALARM_STATISTICS *FalseAlmCnt = &pDM_Odm->FalseAlmCnt;
+ u8 CurCCK_CCAThres;
+
+
+ if (
+ !(pDM_Odm->SupportAbility & ODM_BB_CCK_PD) ||
+ !(pDM_Odm->SupportAbility & ODM_BB_FA_CNT)
+ ) {
+ return;
+ }
+
+ if (pDM_Odm->ExtLNA)
+ return;
+
+ if (pDM_Odm->bLinked) {
+ if (pDM_Odm->RSSI_Min > 25)
+ CurCCK_CCAThres = 0xcd;
+ else if ((pDM_Odm->RSSI_Min <= 25) && (pDM_Odm->RSSI_Min > 10))
+ CurCCK_CCAThres = 0x83;
+ else {
+ if (FalseAlmCnt->Cnt_Cck_fail > 1000)
+ CurCCK_CCAThres = 0x83;
+ else
+ CurCCK_CCAThres = 0x40;
+ }
+ } else {
+ if (FalseAlmCnt->Cnt_Cck_fail > 1000)
+ CurCCK_CCAThres = 0x83;
+ else
+ CurCCK_CCAThres = 0x40;
+ }
+
+ ODM_Write_CCK_CCA_Thres(pDM_Odm, CurCCK_CCAThres);
+}
+
+void ODM_Write_CCK_CCA_Thres(void *pDM_VOID, u8 CurCCK_CCAThres)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+ struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
+
+ /* modify by Guo.Mingzhi 2012-01-03 */
+ if (pDM_DigTable->CurCCK_CCAThres != CurCCK_CCAThres)
+ rtw_write8(pDM_Odm->Adapter, ODM_REG(CCK_CCA, pDM_Odm), CurCCK_CCAThres);
+
+ pDM_DigTable->PreCCK_CCAThres = pDM_DigTable->CurCCK_CCAThres;
+ pDM_DigTable->CurCCK_CCAThres = CurCCK_CCAThres;
+}
diff --git a/drivers/staging/rtl8723bs/hal/odm_DIG.h b/drivers/staging/rtl8723bs/hal/odm_DIG.h
new file mode 100644
index 000000000..a5b041101
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/odm_DIG.h
@@ -0,0 +1,169 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#ifndef __ODMDIG_H__
+#define __ODMDIG_H__
+
+struct dig_t { /* _Dynamic_Initial_Gain_Threshold_ */
+ bool bStopDIG;
+ bool bPSDInProgress;
+
+ u8 Dig_Enable_Flag;
+ u8 Dig_Ext_Port_Stage;
+
+ int RssiLowThresh;
+ int RssiHighThresh;
+
+ u32 FALowThresh;
+ u32 FAHighThresh;
+
+ u8 CurSTAConnectState;
+ u8 PreSTAConnectState;
+ u8 CurMultiSTAConnectState;
+
+ u8 PreIGValue;
+ u8 CurIGValue;
+ u8 BackupIGValue; /* MP DIG */
+ u8 BT30_CurIGI;
+ u8 IGIBackup;
+
+ s8 BackoffVal;
+ s8 BackoffVal_range_max;
+ s8 BackoffVal_range_min;
+ u8 rx_gain_range_max;
+ u8 rx_gain_range_min;
+ u8 Rssi_val_min;
+
+ u8 PreCCK_CCAThres;
+ u8 CurCCK_CCAThres;
+ u8 PreCCKPDState;
+ u8 CurCCKPDState;
+ u8 CCKPDBackup;
+
+ u8 LargeFAHit;
+ u8 ForbiddenIGI;
+ u32 Recover_cnt;
+
+ u8 DIG_Dynamic_MIN_0;
+ u8 DIG_Dynamic_MIN_1;
+ bool bMediaConnect_0;
+ bool bMediaConnect_1;
+
+ u32 AntDiv_RSSI_max;
+ u32 RSSI_max;
+
+ u8 *pbP2pLinkInProgress;
+};
+
+struct false_ALARM_STATISTICS {
+ u32 Cnt_Parity_Fail;
+ u32 Cnt_Rate_Illegal;
+ u32 Cnt_Crc8_fail;
+ u32 Cnt_Mcs_fail;
+ u32 Cnt_Ofdm_fail;
+ u32 Cnt_Ofdm_fail_pre; /* For RTL8881A */
+ u32 Cnt_Cck_fail;
+ u32 Cnt_all;
+ u32 Cnt_Fast_Fsync;
+ u32 Cnt_SB_Search_fail;
+ u32 Cnt_OFDM_CCA;
+ u32 Cnt_CCK_CCA;
+ u32 Cnt_CCA_all;
+ u32 Cnt_BW_USC; /* Gary */
+ u32 Cnt_BW_LSC; /* Gary */
+};
+
+enum ODM_Pause_DIG_TYPE {
+ ODM_PAUSE_DIG = BIT0,
+ ODM_RESUME_DIG = BIT1
+};
+
+#define DM_DIG_THRESH_HIGH 40
+#define DM_DIG_THRESH_LOW 35
+
+#define DMfalseALARM_THRESH_LOW 400
+#define DMfalseALARM_THRESH_HIGH 1000
+
+#define DM_DIG_MAX_NIC 0x3e
+#define DM_DIG_MIN_NIC 0x1e /* 0x22//0x1c */
+#define DM_DIG_MAX_OF_MIN_NIC 0x3e
+
+#define DM_DIG_MAX_AP 0x3e
+#define DM_DIG_MIN_AP 0x1c
+#define DM_DIG_MAX_OF_MIN 0x2A /* 0x32 */
+#define DM_DIG_MIN_AP_DFS 0x20
+
+#define DM_DIG_MAX_NIC_HP 0x46
+#define DM_DIG_MIN_NIC_HP 0x2e
+
+#define DM_DIG_MAX_AP_HP 0x42
+#define DM_DIG_MIN_AP_HP 0x30
+
+#define DM_DIG_FA_TH0 0x200/* 0x20 */
+
+#define DM_DIG_FA_TH1 0x300
+#define DM_DIG_FA_TH2 0x400
+/* this is for 92d */
+#define DM_DIG_FA_TH0_92D 0x100
+#define DM_DIG_FA_TH1_92D 0x400
+#define DM_DIG_FA_TH2_92D 0x600
+
+#define DM_DIG_BACKOFF_MAX 12
+#define DM_DIG_BACKOFF_MIN -4
+#define DM_DIG_BACKOFF_DEFAULT 10
+
+#define DM_DIG_FA_TH0_LPS 4 /* 4 in lps */
+#define DM_DIG_FA_TH1_LPS 15 /* 15 lps */
+#define DM_DIG_FA_TH2_LPS 30 /* 30 lps */
+#define RSSI_OFFSET_DIG 0x05
+
+void odm_NHMCounterStatisticsInit(void *pDM_VOID);
+
+void odm_NHMCounterStatistics(void *pDM_VOID);
+
+void odm_NHMBBInit(void *pDM_VOID);
+
+void odm_NHMBB(void *pDM_VOID);
+
+void odm_NHMCounterStatisticsReset(void *pDM_VOID);
+
+void odm_GetNHMCounterStatistics(void *pDM_VOID);
+
+void odm_SearchPwdBLowerBound(void *pDM_VOID, u8 IGI_target);
+
+void odm_AdaptivityInit(void *pDM_VOID);
+
+void odm_Adaptivity(void *pDM_VOID, u8 IGI);
+
+void ODM_Write_DIG(void *pDM_VOID, u8 CurrentIGI);
+
+void odm_DIGInit(void *pDM_VOID);
+
+void odm_DIG(void *pDM_VOID);
+
+void odm_DIGbyRSSI_LPS(void *pDM_VOID);
+
+void odm_FalseAlarmCounterStatistics(void *pDM_VOID);
+
+void odm_FAThresholdCheck(
+ void *pDM_VOID,
+ bool bDFSBand,
+ bool bPerformance,
+ u32 RxTp,
+ u32 TxTp,
+ u32 *dm_FA_thres
+);
+
+u8 odm_ForbiddenIGICheck(void *pDM_VOID, u8 DIG_Dynamic_MIN, u8 CurrentIGI);
+
+bool odm_DigAbort(void *pDM_VOID);
+
+void odm_CCKPacketDetectionThresh(void *pDM_VOID);
+
+void ODM_Write_CCK_CCA_Thres(void *pDM_VOID, u8 CurCCK_CCAThres);
+
+#endif
diff --git a/drivers/staging/rtl8723bs/hal/odm_DynamicBBPowerSaving.c b/drivers/staging/rtl8723bs/hal/odm_DynamicBBPowerSaving.c
new file mode 100644
index 000000000..57c573652
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/odm_DynamicBBPowerSaving.c
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include "odm_precomp.h"
+
+void odm_DynamicBBPowerSavingInit(void *pDM_VOID)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+ struct ps_t *pDM_PSTable = &pDM_Odm->DM_PSTable;
+
+ pDM_PSTable->PreCCAState = CCA_MAX;
+ pDM_PSTable->CurCCAState = CCA_MAX;
+ pDM_PSTable->PreRFState = RF_MAX;
+ pDM_PSTable->CurRFState = RF_MAX;
+ pDM_PSTable->Rssi_val_min = 0;
+ pDM_PSTable->initialize = 0;
+}
+
+void ODM_RF_Saving(void *pDM_VOID, u8 bForceInNormal)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+ struct ps_t *pDM_PSTable = &pDM_Odm->DM_PSTable;
+ u8 Rssi_Up_bound = 30;
+ u8 Rssi_Low_bound = 25;
+
+ if (pDM_Odm->PatchID == 40) { /* RT_CID_819x_FUNAI_TV */
+ Rssi_Up_bound = 50;
+ Rssi_Low_bound = 45;
+ }
+
+ if (pDM_PSTable->initialize == 0) {
+
+ pDM_PSTable->Reg874 = (PHY_QueryBBReg(pDM_Odm->Adapter, 0x874, bMaskDWord)&0x1CC000)>>14;
+ pDM_PSTable->RegC70 = (PHY_QueryBBReg(pDM_Odm->Adapter, 0xc70, bMaskDWord)&BIT3)>>3;
+ pDM_PSTable->Reg85C = (PHY_QueryBBReg(pDM_Odm->Adapter, 0x85c, bMaskDWord)&0xFF000000)>>24;
+ pDM_PSTable->RegA74 = (PHY_QueryBBReg(pDM_Odm->Adapter, 0xa74, bMaskDWord)&0xF000)>>12;
+ /* Reg818 = PHY_QueryBBReg(padapter, 0x818, bMaskDWord); */
+ pDM_PSTable->initialize = 1;
+ }
+
+ if (!bForceInNormal) {
+ if (pDM_Odm->RSSI_Min != 0xFF) {
+ if (pDM_PSTable->PreRFState == RF_Normal) {
+ if (pDM_Odm->RSSI_Min >= Rssi_Up_bound)
+ pDM_PSTable->CurRFState = RF_Save;
+ else
+ pDM_PSTable->CurRFState = RF_Normal;
+ } else {
+ if (pDM_Odm->RSSI_Min <= Rssi_Low_bound)
+ pDM_PSTable->CurRFState = RF_Normal;
+ else
+ pDM_PSTable->CurRFState = RF_Save;
+ }
+ } else
+ pDM_PSTable->CurRFState = RF_MAX;
+ } else
+ pDM_PSTable->CurRFState = RF_Normal;
+
+ if (pDM_PSTable->PreRFState != pDM_PSTable->CurRFState) {
+ if (pDM_PSTable->CurRFState == RF_Save) {
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x874, 0x1C0000, 0x2); /* Reg874[20:18]=3'b010 */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0xc70, BIT3, 0); /* RegC70[3]= 1'b0 */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x85c, 0xFF000000, 0x63); /* Reg85C[31:24]= 0x63 */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x874, 0xC000, 0x2); /* Reg874[15:14]=2'b10 */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0xa74, 0xF000, 0x3); /* RegA75[7:4]= 0x3 */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x818, BIT28, 0x0); /* Reg818[28]= 1'b0 */
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x818, BIT28, 0x1); /* Reg818[28]= 1'b1 */
+ } else {
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x874, 0x1CC000, pDM_PSTable->Reg874);
+ PHY_SetBBReg(pDM_Odm->Adapter, 0xc70, BIT3, pDM_PSTable->RegC70);
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x85c, 0xFF000000, pDM_PSTable->Reg85C);
+ PHY_SetBBReg(pDM_Odm->Adapter, 0xa74, 0xF000, pDM_PSTable->RegA74);
+ PHY_SetBBReg(pDM_Odm->Adapter, 0x818, BIT28, 0x0);
+ }
+ pDM_PSTable->PreRFState = pDM_PSTable->CurRFState;
+ }
+}
diff --git a/drivers/staging/rtl8723bs/hal/odm_DynamicBBPowerSaving.h b/drivers/staging/rtl8723bs/hal/odm_DynamicBBPowerSaving.h
new file mode 100644
index 000000000..3ebbbfd1d
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/odm_DynamicBBPowerSaving.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#ifndef __ODMDYNAMICBBPOWERSAVING_H__
+#define __ODMDYNAMICBBPOWERSAVING_H__
+
+struct ps_t { /* _Dynamic_Power_Saving_ */
+ u8 PreCCAState;
+ u8 CurCCAState;
+
+ u8 PreRFState;
+ u8 CurRFState;
+
+ int Rssi_val_min;
+
+ u8 initialize;
+ u32 Reg874, RegC70, Reg85C, RegA74;
+
+};
+
+#define dm_RF_Saving ODM_RF_Saving
+
+void ODM_RF_Saving(void *pDM_VOID, u8 bForceInNormal);
+
+void odm_DynamicBBPowerSavingInit(void *pDM_VOID);
+
+#endif
diff --git a/drivers/staging/rtl8723bs/hal/odm_DynamicTxPower.c b/drivers/staging/rtl8723bs/hal/odm_DynamicTxPower.c
new file mode 100644
index 000000000..398dfa134
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/odm_DynamicTxPower.c
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include "odm_precomp.h"
+
+void odm_DynamicTxPowerInit(void *pDM_VOID)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+ struct dm_priv *pdmpriv = &pHalData->dmpriv;
+
+ pdmpriv->bDynamicTxPowerEnable = false;
+
+ pdmpriv->LastDTPLvl = TxHighPwrLevel_Normal;
+ pdmpriv->DynamicTxHighPowerLvl = TxHighPwrLevel_Normal;
+}
diff --git a/drivers/staging/rtl8723bs/hal/odm_DynamicTxPower.h b/drivers/staging/rtl8723bs/hal/odm_DynamicTxPower.h
new file mode 100644
index 000000000..e2d244324
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/odm_DynamicTxPower.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#ifndef __ODMDYNAMICTXPOWER_H__
+#define __ODMDYNAMICTXPOWER_H__
+
+#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74
+#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67
+#define TX_POWER_NEAR_FIELD_THRESH_AP 0x3F
+#define TX_POWER_NEAR_FIELD_THRESH_8812 60
+
+#define TxHighPwrLevel_Normal 0
+#define TxHighPwrLevel_Level1 1
+#define TxHighPwrLevel_Level2 2
+#define TxHighPwrLevel_BT1 3
+#define TxHighPwrLevel_BT2 4
+#define TxHighPwrLevel_15 5
+#define TxHighPwrLevel_35 6
+#define TxHighPwrLevel_50 7
+#define TxHighPwrLevel_70 8
+#define TxHighPwrLevel_100 9
+
+void odm_DynamicTxPowerInit(void *pDM_VOID);
+
+#endif
diff --git a/drivers/staging/rtl8723bs/hal/odm_EdcaTurboCheck.c b/drivers/staging/rtl8723bs/hal/odm_EdcaTurboCheck.c
new file mode 100644
index 000000000..578d57126
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/odm_EdcaTurboCheck.c
@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include "odm_precomp.h"
+
+static u32 edca_setting_DL_GMode[HT_IOT_PEER_MAX] = {
+/*UNKNOWN, REALTEK_90, ALTEK_92SE BROADCOM, LINK ATHEROS,
+ *CISCO, MERU, MARVELL, 92U_AP, SELF_AP
+ */
+ 0x4322, 0xa44f, 0x5e4322, 0xa42b, 0x5e4322, 0x4322,
+ 0xa42b, 0x5ea42b, 0xa44f, 0x5e4322, 0x5ea42b
+};
+
+static u32 edca_setting_UL[HT_IOT_PEER_MAX] = {
+/*UNKNOWN, REALTEK_90, REALTEK_92SE, BROADCOM, RALINK, ATHEROS,
+ *CISCO, MERU, MARVELL, 92U_AP, SELF_AP(DownLink/Tx)
+ */
+ 0x5e4322, 0xa44f, 0x5e4322, 0x5ea32b, 0x5ea422, 0x5ea322,
+ 0x3ea430, 0x5ea42b, 0x5ea44f, 0x5e4322, 0x5e4322};
+
+static u32 edca_setting_DL[HT_IOT_PEER_MAX] = {
+/*UNKNOWN, REALTEK_90, REALTEK_92SE, BROADCOM, RALINK, ATHEROS,
+ *CISCO, MERU, MARVELL, 92U_AP, SELF_AP(UpLink/Rx)
+ */
+ 0xa44f, 0x5ea44f, 0x5e4322, 0x5ea42b, 0xa44f, 0xa630,
+ 0x5ea630, 0x5ea42b, 0xa44f, 0xa42b, 0xa42b};
+
+void ODM_EdcaTurboInit(void *pDM_VOID)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+ struct adapter *Adapter = pDM_Odm->Adapter;
+
+ pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false;
+ pDM_Odm->DM_EDCA_Table.bIsCurRDLState = false;
+ Adapter->recvpriv.bIsAnyNonBEPkts = false;
+} /* ODM_InitEdcaTurbo */
+
+void odm_EdcaTurboCheck(void *pDM_VOID)
+{
+ /* In HW integration first stage, we provide 4 different handles to
+ * operate at the same time. In stage2/3, we need to prove universal
+ * interface and merge all HW dynamic mechanism.
+ */
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+
+ if (!(pDM_Odm->SupportAbility & ODM_MAC_EDCA_TURBO))
+ return;
+
+ odm_EdcaTurboCheckCE(pDM_Odm);
+} /* odm_CheckEdcaTurbo */
+
+void odm_EdcaTurboCheckCE(void *pDM_VOID)
+{
+ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(Adapter);
+ struct recv_priv *precvpriv = &(Adapter->recvpriv);
+ struct registry_priv *pregpriv = &Adapter->registrypriv;
+ struct mlme_ext_priv *pmlmeext = &(Adapter->mlmeextpriv);
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+ u32 EDCA_BE_UL = 0x5ea42b;
+ u32 EDCA_BE_DL = 0x5ea42b;
+ u32 iot_peer = 0;
+ u8 wirelessmode = 0xFF; /* invalid value */
+ u32 trafficIndex;
+ u32 edca_param;
+ u64 cur_tx_bytes = 0;
+ u64 cur_rx_bytes = 0;
+ u8 bbtchange = false;
+ u8 biasonrx = false;
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+
+ if (!pDM_Odm->bLinked) {
+ precvpriv->bIsAnyNonBEPkts = false;
+ return;
+ }
+
+ if (pregpriv->wifi_spec == 1) {
+ precvpriv->bIsAnyNonBEPkts = false;
+ return;
+ }
+
+ if (pDM_Odm->pwirelessmode)
+ wirelessmode = *(pDM_Odm->pwirelessmode);
+
+ iot_peer = pmlmeinfo->assoc_AP_vendor;
+
+ if (iot_peer >= HT_IOT_PEER_MAX) {
+ precvpriv->bIsAnyNonBEPkts = false;
+ return;
+ }
+
+ /* Check if the status needs to be changed. */
+ if ((bbtchange) || (!precvpriv->bIsAnyNonBEPkts)) {
+ cur_tx_bytes = pdvobjpriv->traffic_stat.cur_tx_bytes;
+ cur_rx_bytes = pdvobjpriv->traffic_stat.cur_rx_bytes;
+
+ /* traffic, TX or RX */
+ if (biasonrx) {
+ if (cur_tx_bytes > (cur_rx_bytes << 2)) {
+ /* Uplink TP is present. */
+ trafficIndex = UP_LINK;
+ } else { /* Balance TP is present. */
+ trafficIndex = DOWN_LINK;
+ }
+ } else {
+ if (cur_rx_bytes > (cur_tx_bytes << 2)) {
+ /* Downlink TP is present. */
+ trafficIndex = DOWN_LINK;
+ } else { /* Balance TP is present. */
+ trafficIndex = UP_LINK;
+ }
+ }
+
+ /* 92D txop can't be set to 0x3e for cisco1250 */
+ if ((iot_peer == HT_IOT_PEER_CISCO) &&
+ (wirelessmode == ODM_WM_N24G)) {
+ EDCA_BE_DL = edca_setting_DL[iot_peer];
+ EDCA_BE_UL = edca_setting_UL[iot_peer];
+ } else if ((iot_peer == HT_IOT_PEER_CISCO) &&
+ ((wirelessmode == ODM_WM_G) ||
+ (wirelessmode == (ODM_WM_B | ODM_WM_G)) ||
+ (wirelessmode == ODM_WM_B))) {
+ EDCA_BE_DL = edca_setting_DL_GMode[iot_peer];
+ } else if ((iot_peer == HT_IOT_PEER_AIRGO) &&
+ (wirelessmode == ODM_WM_G)) {
+ EDCA_BE_DL = 0xa630;
+ } else if (iot_peer == HT_IOT_PEER_MARVELL) {
+ EDCA_BE_DL = edca_setting_DL[iot_peer];
+ EDCA_BE_UL = edca_setting_UL[iot_peer];
+ } else if (iot_peer == HT_IOT_PEER_ATHEROS) {
+ /* Set DL EDCA for Atheros peer to 0x3ea42b. */
+ EDCA_BE_DL = edca_setting_DL[iot_peer];
+ }
+
+ if (trafficIndex == DOWN_LINK)
+ edca_param = EDCA_BE_DL;
+ else
+ edca_param = EDCA_BE_UL;
+
+ rtw_write32(Adapter, REG_EDCA_BE_PARAM, edca_param);
+
+ pDM_Odm->DM_EDCA_Table.prv_traffic_idx = trafficIndex;
+
+ pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = true;
+ } else {
+ /* Turn Off EDCA turbo here. */
+ /* Restore original EDCA according to the declaration of AP. */
+ if (pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA) {
+ rtw_write32(Adapter, REG_EDCA_BE_PARAM, pHalData->AcParam_BE);
+ pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false;
+ }
+ }
+}
diff --git a/drivers/staging/rtl8723bs/hal/odm_EdcaTurboCheck.h b/drivers/staging/rtl8723bs/hal/odm_EdcaTurboCheck.h
new file mode 100644
index 000000000..e9f9f0722
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/odm_EdcaTurboCheck.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#ifndef __ODMEDCATURBOCHECK_H__
+#define __ODMEDCATURBOCHECK_H__
+
+struct edca_t { /* _EDCA_TURBO_ */
+ bool bCurrentTurboEDCA;
+ bool bIsCurRDLState;
+
+ u32 prv_traffic_idx; /* edca turbo */
+};
+
+void odm_EdcaTurboCheck(void *pDM_VOID);
+void ODM_EdcaTurboInit(void *pDM_VOID);
+
+void odm_EdcaTurboCheckCE(void *pDM_VOID);
+
+#endif
diff --git a/drivers/staging/rtl8723bs/hal/odm_HWConfig.c b/drivers/staging/rtl8723bs/hal/odm_HWConfig.c
new file mode 100644
index 000000000..994b8c578
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/odm_HWConfig.c
@@ -0,0 +1,446 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include "odm_precomp.h"
+
+#define READ_AND_CONFIG_MP(ic, txt) (ODM_ReadAndConfig_MP_##ic##txt(pDM_Odm))
+#define READ_AND_CONFIG READ_AND_CONFIG_MP
+
+static u8 odm_query_rx_pwr_percentage(s8 ant_power)
+{
+ if ((ant_power <= -100) || (ant_power >= 20))
+ return 0;
+ else if (ant_power >= 0)
+ return 100;
+ else
+ return 100 + ant_power;
+
+}
+
+s32 odm_signal_scale_mapping(struct dm_odm_t *dm_odm, s32 curr_sig)
+{
+ s32 ret_sig = 0;
+
+ if (dm_odm->SupportInterface == ODM_ITRF_SDIO) {
+ if (curr_sig >= 51 && curr_sig <= 100)
+ ret_sig = 100;
+ else if (curr_sig >= 41 && curr_sig <= 50)
+ ret_sig = 80 + ((curr_sig - 40)*2);
+ else if (curr_sig >= 31 && curr_sig <= 40)
+ ret_sig = 66 + (curr_sig - 30);
+ else if (curr_sig >= 21 && curr_sig <= 30)
+ ret_sig = 54 + (curr_sig - 20);
+ else if (curr_sig >= 10 && curr_sig <= 20)
+ ret_sig = 42 + (((curr_sig - 10) * 2) / 3);
+ else if (curr_sig >= 5 && curr_sig <= 9)
+ ret_sig = 22 + (((curr_sig - 5) * 3) / 2);
+ else if (curr_sig >= 1 && curr_sig <= 4)
+ ret_sig = 6 + (((curr_sig - 1) * 3) / 2);
+ else
+ ret_sig = curr_sig;
+ }
+
+ return ret_sig;
+}
+
+static u8 odm_evm_db_to_percentage(s8 value)
+{
+ /* */
+ /* -33dB~0dB to 0%~99% */
+ /* */
+ s8 ret_val;
+
+ ret_val = value;
+ ret_val /= 2;
+
+ if (ret_val >= 0)
+ ret_val = 0;
+ if (ret_val <= -33)
+ ret_val = -33;
+
+ ret_val = 0 - ret_val;
+ ret_val *= 3;
+
+ if (ret_val == 99)
+ ret_val = 100;
+
+ return ret_val;
+}
+
+static s8 odm_cck_rssi(u8 lna_idx, u8 vga_idx)
+{
+ s8 rx_pwr_all = 0x00;
+
+ switch (lna_idx) {
+ /* 46 53 73 95 201301231630 */
+ /* 46 53 77 99 201301241630 */
+
+ case 6:
+ rx_pwr_all = -34 - (2 * vga_idx);
+ break;
+ case 4:
+ rx_pwr_all = -14 - (2 * vga_idx);
+ break;
+ case 1:
+ rx_pwr_all = 6 - (2 * vga_idx);
+ break;
+ case 0:
+ rx_pwr_all = 16 - (2 * vga_idx);
+ break;
+ default:
+ /* rx_pwr_all = -53+(2*(31-VGA_idx)); */
+ break;
+ }
+ return rx_pwr_all;
+}
+
+static void odm_rx_phy_status_parsing(struct dm_odm_t *dm_odm,
+ struct odm_phy_info *phy_info,
+ u8 *phy_status,
+ struct odm_packet_info *pkt_info)
+{
+ u8 i;
+ s8 rx_pwr[4], rx_pwr_all = 0;
+ u8 evm, pwdb_all = 0, pwdb_all_bt;
+ u8 rssi, total_rssi = 0;
+ bool is_cck_rate = false;
+ u8 rf_rx_num = 0;
+ u8 lna_idx, vga_idx;
+ struct phy_status_rpt_8192cd_t *phy_sta_rpt = (struct phy_status_rpt_8192cd_t *)phy_status;
+
+ is_cck_rate = pkt_info->data_rate <= DESC_RATE11M;
+ phy_info->rx_mimo_signal_quality[RF_PATH_A] = -1;
+ phy_info->rx_mimo_signal_quality[RF_PATH_B] = -1;
+
+
+ if (is_cck_rate) {
+ u8 cck_agc_rpt;
+
+ dm_odm->PhyDbgInfo.NumQryPhyStatusCCK++;
+
+ /*
+ * (1)Hardware does not provide RSSI for CCK/
+ * (2)PWDB, Average PWDB calculated by
+ * hardware (for rate adaptive)
+ */
+
+ cck_agc_rpt = phy_sta_rpt->cck_agc_rpt_ofdm_cfosho_a;
+
+ /*
+ * 2011.11.28 LukeLee: 88E use different LNA & VGA gain table
+ * The RSSI formula should be modified according to the gain table
+ */
+ lna_idx = ((cck_agc_rpt & 0xE0)>>5);
+ vga_idx = (cck_agc_rpt & 0x1F);
+ rx_pwr_all = odm_cck_rssi(lna_idx, vga_idx);
+ pwdb_all = odm_query_rx_pwr_percentage(rx_pwr_all);
+ if (pwdb_all > 100)
+ pwdb_all = 100;
+
+ phy_info->rx_pwd_ba11 = pwdb_all;
+ phy_info->bt_rx_rssi_percentage = pwdb_all;
+ phy_info->recv_signal_power = rx_pwr_all;
+
+ /* (3) Get Signal Quality (EVM) */
+
+ /* if (pPktinfo->bPacketMatchBSSID) */
+ {
+ u8 sq, sq_rpt;
+
+ if (phy_info->rx_pwd_ba11 > 40 && !dm_odm->bInHctTest)
+ sq = 100;
+ else {
+ sq_rpt = phy_sta_rpt->cck_sig_qual_ofdm_pwdb_all;
+
+ if (sq_rpt > 64)
+ sq = 0;
+ else if (sq_rpt < 20)
+ sq = 100;
+ else
+ sq = ((64-sq_rpt) * 100) / 44;
+
+ }
+
+ phy_info->signal_quality = sq;
+ phy_info->rx_mimo_signal_quality[RF_PATH_A] = sq;
+ phy_info->rx_mimo_signal_quality[RF_PATH_B] = -1;
+ }
+ } else { /* is OFDM rate */
+ dm_odm->PhyDbgInfo.NumQryPhyStatusOFDM++;
+
+ /*
+ * (1)Get RSSI for HT rate
+ */
+
+ for (i = RF_PATH_A; i < RF_PATH_MAX; i++) {
+ /* 2008/01/30 MH we will judge RF RX path now. */
+ if (dm_odm->RFPathRxEnable & BIT(i))
+ rf_rx_num++;
+ /* else */
+ /* continue; */
+
+ rx_pwr[i] = ((phy_sta_rpt->path_agc[i].gain & 0x3F) * 2) - 110;
+
+ phy_info->rx_pwr[i] = rx_pwr[i];
+
+ /* Translate DBM to percentage. */
+ rssi = odm_query_rx_pwr_percentage(rx_pwr[i]);
+ total_rssi += rssi;
+
+ phy_info->rx_mimo_signal_strength[i] = (u8)rssi;
+
+ /* Get Rx snr value in DB */
+ phy_info->rx_snr[i] = dm_odm->PhyDbgInfo.RxSNRdB[i] = (s32)(phy_sta_rpt->path_rxsnr[i]/2);
+ }
+
+ /*
+ * (2)PWDB, Average PWDB calculated by hardware (for rate adaptive)
+ */
+ rx_pwr_all = ((phy_sta_rpt->cck_sig_qual_ofdm_pwdb_all >> 1) & 0x7f) - 110;
+
+ pwdb_all_bt = pwdb_all = odm_query_rx_pwr_percentage(rx_pwr_all);
+
+ phy_info->rx_pwd_ba11 = pwdb_all;
+ phy_info->bt_rx_rssi_percentage = pwdb_all_bt;
+ phy_info->rx_power = rx_pwr_all;
+ phy_info->recv_signal_power = rx_pwr_all;
+
+ /*
+ * (3)EVM of HT rate
+ *
+ * Only spatial stream 1 makes sense
+ *
+ * Do not use shift operation like "rx_evmX >>= 1"
+ * because the compiler of free build environment
+ * fill most significant bit to "zero" when doing
+ * shifting operation which may change a negative
+ * value to positive one, then the dbm value (which
+ * is supposed to be negative) is not correct
+ * anymore.
+ */
+ evm = odm_evm_db_to_percentage(phy_sta_rpt->stream_rxevm[0]); /* dbm */
+
+ /* Fill value in RFD, Get the first spatial stream only */
+ phy_info->signal_quality = (u8)(evm & 0xff);
+
+ phy_info->rx_mimo_signal_quality[RF_PATH_A] = (u8)(evm & 0xff);
+
+ odm_parsing_cfo(dm_odm, pkt_info, phy_sta_rpt->path_cfotail);
+ }
+
+ /*
+ * UI BSS List signal strength(in percentage), make it good
+ * looking, from 0~100.
+ * It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp().
+ */
+ if (is_cck_rate) {
+ phy_info->signal_strength = (u8)(odm_signal_scale_mapping(dm_odm, pwdb_all));
+ } else {
+ if (rf_rx_num != 0) {
+ phy_info->signal_strength = (u8)(odm_signal_scale_mapping(dm_odm, total_rssi /= rf_rx_num));
+ }
+ }
+}
+
+static void odm_Process_RSSIForDM(
+ struct dm_odm_t *pDM_Odm, struct odm_phy_info *pPhyInfo, struct odm_packet_info *pPktinfo
+)
+{
+
+ s32 UndecoratedSmoothedPWDB, UndecoratedSmoothedCCK, UndecoratedSmoothedOFDM, RSSI_Ave;
+ u8 isCCKrate = 0;
+ u8 RSSI_max, RSSI_min, i;
+ u32 OFDM_pkt = 0;
+ u32 Weighting = 0;
+ PSTA_INFO_T pEntry;
+
+
+ if (pPktinfo->station_id == 0xFF)
+ return;
+
+ pEntry = pDM_Odm->pODM_StaInfo[pPktinfo->station_id];
+
+ if (!IS_STA_VALID(pEntry))
+ return;
+
+ if ((!pPktinfo->bssid_match))
+ return;
+
+ if (pPktinfo->is_beacon)
+ pDM_Odm->PhyDbgInfo.NumQryBeaconPkt++;
+
+ isCCKrate = ((pPktinfo->data_rate <= DESC_RATE11M)) ? true : false;
+ pDM_Odm->RxRate = pPktinfo->data_rate;
+
+ /* Statistic for antenna/path diversity------------------ */
+ if (pDM_Odm->SupportAbility & ODM_BB_ANT_DIV) {
+
+ }
+
+ /* Smart Antenna Debug Message------------------ */
+
+ UndecoratedSmoothedCCK = pEntry->rssi_stat.UndecoratedSmoothedCCK;
+ UndecoratedSmoothedOFDM = pEntry->rssi_stat.UndecoratedSmoothedOFDM;
+ UndecoratedSmoothedPWDB = pEntry->rssi_stat.UndecoratedSmoothedPWDB;
+
+ if (pPktinfo->to_self || pPktinfo->is_beacon) {
+
+ if (!isCCKrate) { /* ofdm rate */
+ if (pPhyInfo->rx_mimo_signal_strength[RF_PATH_B] == 0) {
+ RSSI_Ave = pPhyInfo->rx_mimo_signal_strength[RF_PATH_A];
+ pDM_Odm->RSSI_A = pPhyInfo->rx_mimo_signal_strength[RF_PATH_A];
+ pDM_Odm->RSSI_B = 0;
+ } else {
+ pDM_Odm->RSSI_A = pPhyInfo->rx_mimo_signal_strength[RF_PATH_A];
+ pDM_Odm->RSSI_B = pPhyInfo->rx_mimo_signal_strength[RF_PATH_B];
+
+ if (
+ pPhyInfo->rx_mimo_signal_strength[RF_PATH_A] >
+ pPhyInfo->rx_mimo_signal_strength[RF_PATH_B]
+ ) {
+ RSSI_max = pPhyInfo->rx_mimo_signal_strength[RF_PATH_A];
+ RSSI_min = pPhyInfo->rx_mimo_signal_strength[RF_PATH_B];
+ } else {
+ RSSI_max = pPhyInfo->rx_mimo_signal_strength[RF_PATH_B];
+ RSSI_min = pPhyInfo->rx_mimo_signal_strength[RF_PATH_A];
+ }
+
+ if ((RSSI_max-RSSI_min) < 3)
+ RSSI_Ave = RSSI_max;
+ else if ((RSSI_max-RSSI_min) < 6)
+ RSSI_Ave = RSSI_max - 1;
+ else if ((RSSI_max-RSSI_min) < 10)
+ RSSI_Ave = RSSI_max - 2;
+ else
+ RSSI_Ave = RSSI_max - 3;
+ }
+
+ /* 1 Process OFDM RSSI */
+ if (UndecoratedSmoothedOFDM <= 0) /* initialize */
+ UndecoratedSmoothedOFDM = pPhyInfo->rx_pwd_ba11;
+ else {
+ if (pPhyInfo->rx_pwd_ba11 > (u32)UndecoratedSmoothedOFDM) {
+ UndecoratedSmoothedOFDM =
+ ((UndecoratedSmoothedOFDM*(Rx_Smooth_Factor-1)) +
+ RSSI_Ave)/Rx_Smooth_Factor;
+ UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM + 1;
+ } else {
+ UndecoratedSmoothedOFDM =
+ ((UndecoratedSmoothedOFDM*(Rx_Smooth_Factor-1)) +
+ RSSI_Ave)/Rx_Smooth_Factor;
+ }
+ }
+
+ pEntry->rssi_stat.PacketMap = (pEntry->rssi_stat.PacketMap<<1) | BIT0;
+
+ } else {
+ RSSI_Ave = pPhyInfo->rx_pwd_ba11;
+ pDM_Odm->RSSI_A = (u8) pPhyInfo->rx_pwd_ba11;
+ pDM_Odm->RSSI_B = 0;
+
+ /* 1 Process CCK RSSI */
+ if (UndecoratedSmoothedCCK <= 0) /* initialize */
+ UndecoratedSmoothedCCK = pPhyInfo->rx_pwd_ba11;
+ else {
+ if (pPhyInfo->rx_pwd_ba11 > (u32)UndecoratedSmoothedCCK) {
+ UndecoratedSmoothedCCK =
+ ((UndecoratedSmoothedCCK*(Rx_Smooth_Factor-1)) +
+ pPhyInfo->rx_pwd_ba11)/Rx_Smooth_Factor;
+ UndecoratedSmoothedCCK = UndecoratedSmoothedCCK + 1;
+ } else {
+ UndecoratedSmoothedCCK =
+ ((UndecoratedSmoothedCCK*(Rx_Smooth_Factor-1)) +
+ pPhyInfo->rx_pwd_ba11)/Rx_Smooth_Factor;
+ }
+ }
+ pEntry->rssi_stat.PacketMap = pEntry->rssi_stat.PacketMap<<1;
+ }
+
+ /* if (pEntry) */
+ {
+ /* 2011.07.28 LukeLee: modified to prevent unstable CCK RSSI */
+ if (pEntry->rssi_stat.ValidBit >= 64)
+ pEntry->rssi_stat.ValidBit = 64;
+ else
+ pEntry->rssi_stat.ValidBit++;
+
+ for (i = 0; i < pEntry->rssi_stat.ValidBit; i++)
+ OFDM_pkt += (u8)(pEntry->rssi_stat.PacketMap>>i)&BIT0;
+
+ if (pEntry->rssi_stat.ValidBit == 64) {
+ Weighting = ((OFDM_pkt<<4) > 64)?64:(OFDM_pkt<<4);
+ UndecoratedSmoothedPWDB = (Weighting*UndecoratedSmoothedOFDM+(64-Weighting)*UndecoratedSmoothedCCK)>>6;
+ } else {
+ if (pEntry->rssi_stat.ValidBit != 0)
+ UndecoratedSmoothedPWDB = (OFDM_pkt*UndecoratedSmoothedOFDM+(pEntry->rssi_stat.ValidBit-OFDM_pkt)*UndecoratedSmoothedCCK)/pEntry->rssi_stat.ValidBit;
+ else
+ UndecoratedSmoothedPWDB = 0;
+ }
+
+ pEntry->rssi_stat.UndecoratedSmoothedCCK = UndecoratedSmoothedCCK;
+ pEntry->rssi_stat.UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM;
+ pEntry->rssi_stat.UndecoratedSmoothedPWDB = UndecoratedSmoothedPWDB;
+ }
+
+ }
+}
+
+
+/* */
+/* Endianness before calling this API */
+/* */
+void odm_phy_status_query(struct dm_odm_t *dm_odm, struct odm_phy_info *phy_info,
+ u8 *phy_status, struct odm_packet_info *pkt_info)
+{
+
+ odm_rx_phy_status_parsing(dm_odm, phy_info, phy_status, pkt_info);
+
+ if (!dm_odm->RSSI_test)
+ odm_Process_RSSIForDM(dm_odm, phy_info, pkt_info);
+}
+
+/* */
+/* If you want to add a new IC, Please follow below template and generate a new one. */
+/* */
+/* */
+
+enum hal_status ODM_ConfigRFWithHeaderFile(
+ struct dm_odm_t *pDM_Odm,
+ enum ODM_RF_Config_Type ConfigType,
+ enum rf_path eRFPath
+)
+{
+ if (ConfigType == CONFIG_RF_RADIO)
+ READ_AND_CONFIG(8723B, _RadioA);
+ else if (ConfigType == CONFIG_RF_TXPWR_LMT)
+ READ_AND_CONFIG(8723B, _TXPWR_LMT);
+
+ return HAL_STATUS_SUCCESS;
+}
+
+enum hal_status ODM_ConfigRFWithTxPwrTrackHeaderFile(struct dm_odm_t *pDM_Odm)
+{
+ if (pDM_Odm->SupportInterface == ODM_ITRF_SDIO)
+ READ_AND_CONFIG(8723B, _TxPowerTrack_SDIO);
+
+ return HAL_STATUS_SUCCESS;
+}
+
+enum hal_status ODM_ConfigBBWithHeaderFile(
+ struct dm_odm_t *pDM_Odm, enum ODM_BB_Config_Type ConfigType
+)
+{
+ if (ConfigType == CONFIG_BB_PHY_REG)
+ READ_AND_CONFIG(8723B, _PHY_REG);
+ else if (ConfigType == CONFIG_BB_AGC_TAB)
+ READ_AND_CONFIG(8723B, _AGC_TAB);
+ else if (ConfigType == CONFIG_BB_PHY_REG_PG)
+ READ_AND_CONFIG(8723B, _PHY_REG_PG);
+
+ return HAL_STATUS_SUCCESS;
+}
+
diff --git a/drivers/staging/rtl8723bs/hal/odm_HWConfig.h b/drivers/staging/rtl8723bs/hal/odm_HWConfig.h
new file mode 100644
index 000000000..0c3697c38
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/odm_HWConfig.h
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+
+#ifndef __HALHWOUTSRC_H__
+#define __HALHWOUTSRC_H__
+
+/* */
+/* structure and define */
+/* */
+
+struct phy_rx_agc_info_t {
+ #if (ODM_ENDIAN_TYPE == ODM_ENDIAN_LITTLE)
+ u8 gain:7, trsw:1;
+ #else
+ u8 trsw:1, gain:7;
+ #endif
+};
+
+struct phy_status_rpt_8192cd_t {
+ struct phy_rx_agc_info_t path_agc[2];
+ u8 ch_corr[2];
+ u8 cck_sig_qual_ofdm_pwdb_all;
+ u8 cck_agc_rpt_ofdm_cfosho_a;
+ u8 cck_rpt_b_ofdm_cfosho_b;
+ u8 rsvd_1;/* ch_corr_msb; */
+ u8 noise_power_db_msb;
+ s8 path_cfotail[2];
+ u8 pcts_mask[2];
+ s8 stream_rxevm[2];
+ u8 path_rxsnr[2];
+ u8 noise_power_db_lsb;
+ u8 rsvd_2[3];
+ u8 stream_csi[2];
+ u8 stream_target_csi[2];
+ s8 sig_evm;
+ u8 rsvd_3;
+
+#if (ODM_ENDIAN_TYPE == ODM_ENDIAN_LITTLE)
+ u8 antsel_rx_keep_2:1; /* ex_intf_flg:1; */
+ u8 sgi_en:1;
+ u8 rxsc:2;
+ u8 idle_long:1;
+ u8 r_ant_train_en:1;
+ u8 ant_sel_b:1;
+ u8 ant_sel:1;
+#else /* _BIG_ENDIAN_ */
+ u8 ant_sel:1;
+ u8 ant_sel_b:1;
+ u8 r_ant_train_en:1;
+ u8 idle_long:1;
+ u8 rxsc:2;
+ u8 sgi_en:1;
+ u8 antsel_rx_keep_2:1; /* ex_intf_flg:1; */
+#endif
+};
+
+void odm_phy_status_query(struct dm_odm_t *dm_odm, struct odm_phy_info *phy_info,
+ u8 *phy_status, struct odm_packet_info *pkt_info);
+
+enum hal_status ODM_ConfigRFWithTxPwrTrackHeaderFile(struct dm_odm_t *pDM_Odm);
+
+enum hal_status ODM_ConfigRFWithHeaderFile(
+ struct dm_odm_t *pDM_Odm,
+ enum ODM_RF_Config_Type ConfigType,
+ enum rf_path eRFPath
+);
+
+enum hal_status ODM_ConfigBBWithHeaderFile(
+ struct dm_odm_t *pDM_Odm, enum ODM_BB_Config_Type ConfigType
+);
+
+enum hal_status ODM_ConfigFWWithHeaderFile(
+ struct dm_odm_t *pDM_Odm,
+ enum ODM_FW_Config_Type ConfigType,
+ u8 *pFirmware,
+ u32 *pSize
+);
+
+s32 odm_signal_scale_mapping(struct dm_odm_t *pDM_Odm, s32 CurrSig);
+
+#endif
diff --git a/drivers/staging/rtl8723bs/hal/odm_RegConfig8723B.c b/drivers/staging/rtl8723bs/hal/odm_RegConfig8723B.c
new file mode 100644
index 000000000..1df42069b
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/odm_RegConfig8723B.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include "odm_precomp.h"
+
+void odm_ConfigRFReg_8723B(
+ struct dm_odm_t *pDM_Odm,
+ u32 Addr,
+ u32 Data,
+ enum rf_path RF_PATH,
+ u32 RegAddr
+)
+{
+ if (Addr == 0xfe || Addr == 0xffe)
+ msleep(50);
+ else {
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH, RegAddr, bRFRegOffsetMask, Data);
+ /* Add 1us delay between BB/RF register setting. */
+ udelay(1);
+
+ /* For disable/enable test in high temperature, the B6 value will fail to fill. Suggestion by BB Stanley, 2013.06.25. */
+ if (Addr == 0xb6) {
+ u32 getvalue = 0;
+ u8 count = 0;
+
+ getvalue = PHY_QueryRFReg(
+ pDM_Odm->Adapter, RF_PATH, Addr, bMaskDWord
+ );
+
+ udelay(1);
+
+ while ((getvalue>>8) != (Data>>8)) {
+ count++;
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH, RegAddr, bRFRegOffsetMask, Data);
+ udelay(1);
+ getvalue = PHY_QueryRFReg(pDM_Odm->Adapter, RF_PATH, Addr, bMaskDWord);
+ if (count > 5)
+ break;
+ }
+ }
+
+ if (Addr == 0xb2) {
+ u32 getvalue = 0;
+ u8 count = 0;
+
+ getvalue = PHY_QueryRFReg(
+ pDM_Odm->Adapter, RF_PATH, Addr, bMaskDWord
+ );
+
+ udelay(1);
+
+ while (getvalue != Data) {
+ count++;
+ PHY_SetRFReg(
+ pDM_Odm->Adapter,
+ RF_PATH,
+ RegAddr,
+ bRFRegOffsetMask,
+ Data
+ );
+ udelay(1);
+ /* Do LCK againg */
+ PHY_SetRFReg(
+ pDM_Odm->Adapter,
+ RF_PATH,
+ 0x18,
+ bRFRegOffsetMask,
+ 0x0fc07
+ );
+ udelay(1);
+ getvalue = PHY_QueryRFReg(
+ pDM_Odm->Adapter, RF_PATH, Addr, bMaskDWord
+ );
+
+ if (count > 5)
+ break;
+ }
+ }
+ }
+}
+
+
+void odm_ConfigRF_RadioA_8723B(struct dm_odm_t *pDM_Odm, u32 Addr, u32 Data)
+{
+ u32 content = 0x1000; /* RF_Content: radioa_txt */
+ u32 maskforPhySet = (u32)(content&0xE000);
+
+ odm_ConfigRFReg_8723B(
+ pDM_Odm,
+ Addr,
+ Data,
+ RF_PATH_A,
+ Addr|maskforPhySet
+ );
+}
+
+void odm_ConfigMAC_8723B(struct dm_odm_t *pDM_Odm, u32 Addr, u8 Data)
+{
+ rtw_write8(pDM_Odm->Adapter, Addr, Data);
+}
+
+void odm_ConfigBB_AGC_8723B(
+ struct dm_odm_t *pDM_Odm,
+ u32 Addr,
+ u32 Bitmask,
+ u32 Data
+)
+{
+ PHY_SetBBReg(pDM_Odm->Adapter, Addr, Bitmask, Data);
+ /* Add 1us delay between BB/RF register setting. */
+ udelay(1);
+}
+
+void odm_ConfigBB_PHY_REG_PG_8723B(
+ struct dm_odm_t *pDM_Odm,
+ u32 RfPath,
+ u32 Addr,
+ u32 Bitmask,
+ u32 Data
+)
+{
+ if (Addr == 0xfe || Addr == 0xffe)
+ msleep(50);
+ else {
+ PHY_StoreTxPowerByRate(pDM_Odm->Adapter, RfPath, Addr, Bitmask, Data);
+ }
+}
+
+void odm_ConfigBB_PHY_8723B(
+ struct dm_odm_t *pDM_Odm,
+ u32 Addr,
+ u32 Bitmask,
+ u32 Data
+)
+{
+ if (Addr == 0xfe)
+ msleep(50);
+ else if (Addr == 0xfd)
+ mdelay(5);
+ else if (Addr == 0xfc)
+ mdelay(1);
+ else if (Addr == 0xfb)
+ udelay(50);
+ else if (Addr == 0xfa)
+ udelay(5);
+ else if (Addr == 0xf9)
+ udelay(1);
+ else {
+ PHY_SetBBReg(pDM_Odm->Adapter, Addr, Bitmask, Data);
+ }
+
+ /* Add 1us delay between BB/RF register setting. */
+ udelay(1);
+}
+
+void odm_ConfigBB_TXPWR_LMT_8723B(
+ struct dm_odm_t *pDM_Odm,
+ u8 *Regulation,
+ u8 *Bandwidth,
+ u8 *RateSection,
+ u8 *RfPath,
+ u8 *Channel,
+ u8 *PowerLimit
+)
+{
+ PHY_SetTxPowerLimit(
+ pDM_Odm->Adapter,
+ Regulation,
+ Bandwidth,
+ RateSection,
+ RfPath,
+ Channel,
+ PowerLimit
+ );
+}
diff --git a/drivers/staging/rtl8723bs/hal/odm_RegConfig8723B.h b/drivers/staging/rtl8723bs/hal/odm_RegConfig8723B.h
new file mode 100644
index 000000000..fba7053ee
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/odm_RegConfig8723B.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __INC_ODM_REGCONFIG_H_8723B
+#define __INC_ODM_REGCONFIG_H_8723B
+
+void odm_ConfigRFReg_8723B(struct dm_odm_t *pDM_Odm,
+ u32 Addr,
+ u32 Data,
+ enum rf_path RF_PATH,
+ u32 RegAddr
+);
+
+void odm_ConfigRF_RadioA_8723B(struct dm_odm_t *pDM_Odm, u32 Addr, u32 Data);
+
+void odm_ConfigMAC_8723B(struct dm_odm_t *pDM_Odm, u32 Addr, u8 Data);
+
+void odm_ConfigBB_AGC_8723B(struct dm_odm_t *pDM_Odm,
+ u32 Addr,
+ u32 Bitmask,
+ u32 Data
+);
+
+void odm_ConfigBB_PHY_REG_PG_8723B(struct dm_odm_t *pDM_Odm, u32 RfPath, u32 Addr,
+ u32 Bitmask, u32 Data);
+
+void odm_ConfigBB_PHY_8723B(struct dm_odm_t *pDM_Odm,
+ u32 Addr,
+ u32 Bitmask,
+ u32 Data
+);
+
+void odm_ConfigBB_TXPWR_LMT_8723B(struct dm_odm_t *pDM_Odm,
+ u8 *Regulation,
+ u8 *Bandwidth,
+ u8 *RateSection,
+ u8 *RfPath,
+ u8 *Channel,
+ u8 *PowerLimit
+);
+
+#endif
diff --git a/drivers/staging/rtl8723bs/hal/odm_RegDefine11N.h b/drivers/staging/rtl8723bs/hal/odm_RegDefine11N.h
new file mode 100644
index 000000000..3c7193889
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/odm_RegDefine11N.h
@@ -0,0 +1,162 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#ifndef __ODM_REGDEFINE11N_H__
+#define __ODM_REGDEFINE11N_H__
+
+
+/* 2 RF REG LIST */
+#define ODM_REG_RF_MODE_11N 0x00
+#define ODM_REG_RF_0B_11N 0x0B
+#define ODM_REG_CHNBW_11N 0x18
+#define ODM_REG_T_METER_11N 0x24
+#define ODM_REG_RF_25_11N 0x25
+#define ODM_REG_RF_26_11N 0x26
+#define ODM_REG_RF_27_11N 0x27
+#define ODM_REG_RF_2B_11N 0x2B
+#define ODM_REG_RF_2C_11N 0x2C
+#define ODM_REG_RXRF_A3_11N 0x3C
+#define ODM_REG_T_METER_92D_11N 0x42
+#define ODM_REG_T_METER_88E_11N 0x42
+
+/* 2 BB REG LIST */
+/* PAGE 8 */
+#define ODM_REG_BB_CTRL_11N 0x800
+#define ODM_REG_RF_PIN_11N 0x804
+#define ODM_REG_PSD_CTRL_11N 0x808
+#define ODM_REG_TX_ANT_CTRL_11N 0x80C
+#define ODM_REG_BB_PWR_SAV5_11N 0x818
+#define ODM_REG_CCK_RPT_FORMAT_11N 0x824
+#define ODM_REG_RX_DEFAULT_A_11N 0x858
+#define ODM_REG_RX_DEFAULT_B_11N 0x85A
+#define ODM_REG_BB_PWR_SAV3_11N 0x85C
+#define ODM_REG_ANTSEL_CTRL_11N 0x860
+#define ODM_REG_RX_ANT_CTRL_11N 0x864
+#define ODM_REG_PIN_CTRL_11N 0x870
+#define ODM_REG_BB_PWR_SAV1_11N 0x874
+#define ODM_REG_ANTSEL_PATH_11N 0x878
+#define ODM_REG_BB_3WIRE_11N 0x88C
+#define ODM_REG_SC_CNT_11N 0x8C4
+#define ODM_REG_PSD_DATA_11N 0x8B4
+#define ODM_REG_PSD_DATA_11N 0x8B4
+#define ODM_REG_NHM_TIMER_11N 0x894
+#define ODM_REG_NHM_TH9_TH10_11N 0x890
+#define ODM_REG_NHM_TH3_TO_TH0_11N 0x898
+#define ODM_REG_NHM_TH7_TO_TH4_11N 0x89c
+#define ODM_REG_NHM_CNT_11N 0x8d8
+/* PAGE 9 */
+#define ODM_REG_DBG_RPT_11N 0x908
+#define ODM_REG_ANT_MAPPING1_11N 0x914
+#define ODM_REG_ANT_MAPPING2_11N 0x918
+/* PAGE A */
+#define ODM_REG_CCK_ANTDIV_PARA1_11N 0xA00
+#define ODM_REG_CCK_CCA_11N 0xA0A
+#define ODM_REG_CCK_ANTDIV_PARA2_11N 0xA0C
+#define ODM_REG_CCK_ANTDIV_PARA3_11N 0xA10
+#define ODM_REG_CCK_ANTDIV_PARA4_11N 0xA14
+#define ODM_REG_CCK_FILTER_PARA1_11N 0xA22
+#define ODM_REG_CCK_FILTER_PARA2_11N 0xA23
+#define ODM_REG_CCK_FILTER_PARA3_11N 0xA24
+#define ODM_REG_CCK_FILTER_PARA4_11N 0xA25
+#define ODM_REG_CCK_FILTER_PARA5_11N 0xA26
+#define ODM_REG_CCK_FILTER_PARA6_11N 0xA27
+#define ODM_REG_CCK_FILTER_PARA7_11N 0xA28
+#define ODM_REG_CCK_FILTER_PARA8_11N 0xA29
+#define ODM_REG_CCK_FA_RST_11N 0xA2C
+#define ODM_REG_CCK_FA_MSB_11N 0xA58
+#define ODM_REG_CCK_FA_LSB_11N 0xA5C
+#define ODM_REG_CCK_CCA_CNT_11N 0xA60
+#define ODM_REG_BB_PWR_SAV4_11N 0xA74
+/* PAGE B */
+#define ODM_REG_LNA_SWITCH_11N 0xB2C
+#define ODM_REG_PATH_SWITCH_11N 0xB30
+#define ODM_REG_RSSI_CTRL_11N 0xB38
+#define ODM_REG_CONFIG_ANTA_11N 0xB68
+#define ODM_REG_RSSI_BT_11N 0xB9C
+/* PAGE C */
+#define ODM_REG_OFDM_FA_HOLDC_11N 0xC00
+#define ODM_REG_BB_RX_PATH_11N 0xC04
+#define ODM_REG_TRMUX_11N 0xC08
+#define ODM_REG_OFDM_FA_RSTC_11N 0xC0C
+#define ODM_REG_RXIQI_MATRIX_11N 0xC14
+#define ODM_REG_TXIQK_MATRIX_LSB1_11N 0xC4C
+#define ODM_REG_IGI_A_11N 0xC50
+#define ODM_REG_ANTDIV_PARA2_11N 0xC54
+#define ODM_REG_IGI_B_11N 0xC58
+#define ODM_REG_ANTDIV_PARA3_11N 0xC5C
+#define ODM_REG_L1SBD_PD_CH_11N 0XC6C
+#define ODM_REG_BB_PWR_SAV2_11N 0xC70
+#define ODM_REG_RX_OFF_11N 0xC7C
+#define ODM_REG_TXIQK_MATRIXA_11N 0xC80
+#define ODM_REG_TXIQK_MATRIXB_11N 0xC88
+#define ODM_REG_TXIQK_MATRIXA_LSB2_11N 0xC94
+#define ODM_REG_TXIQK_MATRIXB_LSB2_11N 0xC9C
+#define ODM_REG_RXIQK_MATRIX_LSB_11N 0xCA0
+#define ODM_REG_ANTDIV_PARA1_11N 0xCA4
+#define ODM_REG_OFDM_FA_TYPE1_11N 0xCF0
+/* PAGE D */
+#define ODM_REG_OFDM_FA_RSTD_11N 0xD00
+#define ODM_REG_BB_ATC_11N 0xD2C
+#define ODM_REG_OFDM_FA_TYPE2_11N 0xDA0
+#define ODM_REG_OFDM_FA_TYPE3_11N 0xDA4
+#define ODM_REG_OFDM_FA_TYPE4_11N 0xDA8
+#define ODM_REG_RPT_11N 0xDF4
+/* PAGE E */
+#define ODM_REG_TXAGC_A_6_18_11N 0xE00
+#define ODM_REG_TXAGC_A_24_54_11N 0xE04
+#define ODM_REG_TXAGC_A_1_MCS32_11N 0xE08
+#define ODM_REG_TXAGC_A_MCS0_3_11N 0xE10
+#define ODM_REG_TXAGC_A_MCS4_7_11N 0xE14
+#define ODM_REG_FPGA0_IQK_11N 0xE28
+#define ODM_REG_TXIQK_TONE_A_11N 0xE30
+#define ODM_REG_RXIQK_TONE_A_11N 0xE34
+#define ODM_REG_TXIQK_PI_A_11N 0xE38
+#define ODM_REG_RXIQK_PI_A_11N 0xE3C
+#define ODM_REG_TXIQK_11N 0xE40
+#define ODM_REG_RXIQK_11N 0xE44
+#define ODM_REG_IQK_AGC_PTS_11N 0xE48
+#define ODM_REG_IQK_AGC_RSP_11N 0xE4C
+#define ODM_REG_BLUETOOTH_11N 0xE6C
+#define ODM_REG_RX_WAIT_CCA_11N 0xE70
+#define ODM_REG_TX_CCK_RFON_11N 0xE74
+#define ODM_REG_TX_CCK_BBON_11N 0xE78
+#define ODM_REG_OFDM_RFON_11N 0xE7C
+#define ODM_REG_OFDM_BBON_11N 0xE80
+#define ODM_REG_TX2RX_11N 0xE84
+#define ODM_REG_TX2TX_11N 0xE88
+#define ODM_REG_RX_CCK_11N 0xE8C
+#define ODM_REG_RX_OFDM_11N 0xED0
+#define ODM_REG_RX_WAIT_RIFS_11N 0xED4
+#define ODM_REG_RX2RX_11N 0xED8
+#define ODM_REG_STANDBY_11N 0xEDC
+#define ODM_REG_SLEEP_11N 0xEE0
+#define ODM_REG_PMPD_ANAEN_11N 0xEEC
+#define ODM_REG_IGI_C_11N 0xF84
+#define ODM_REG_IGI_D_11N 0xF88
+
+/* 2 MAC REG LIST */
+#define ODM_REG_BB_RST_11N 0x02
+#define ODM_REG_ANTSEL_PIN_11N 0x4C
+#define ODM_REG_EARLY_MODE_11N 0x4D0
+#define ODM_REG_RSSI_MONITOR_11N 0x4FE
+#define ODM_REG_EDCA_VO_11N 0x500
+#define ODM_REG_EDCA_VI_11N 0x504
+#define ODM_REG_EDCA_BE_11N 0x508
+#define ODM_REG_EDCA_BK_11N 0x50C
+#define ODM_REG_TXPAUSE_11N 0x522
+#define ODM_REG_RESP_TX_11N 0x6D8
+#define ODM_REG_ANT_TRAIN_PARA1_11N 0x7b0
+#define ODM_REG_ANT_TRAIN_PARA2_11N 0x7b4
+
+
+/* DIG Related */
+#define ODM_BIT_IGI_11N 0x0000007F
+#define ODM_BIT_CCK_RPT_FORMAT_11N BIT9
+#define ODM_BIT_BB_RX_PATH_11N 0xF
+#define ODM_BIT_BB_ATC_11N BIT11
+
+#endif
diff --git a/drivers/staging/rtl8723bs/hal/odm_interface.h b/drivers/staging/rtl8723bs/hal/odm_interface.h
new file mode 100644
index 000000000..d19347b02
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/odm_interface.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+
+#ifndef __ODM_INTERFACE_H__
+#define __ODM_INTERFACE_H__
+
+
+
+/* =========== Macro Define */
+
+#define _reg_all(_name) ODM_##_name
+#define _reg_ic(_name, _ic) ODM_##_name##_ic
+#define _bit_all(_name) BIT_##_name
+#define _bit_ic(_name, _ic) BIT_##_name##_ic
+
+/*===================================
+
+#define ODM_REG_DIG_11N 0xC50
+#define ODM_REG_DIG_11AC 0xDDD
+
+ODM_REG(DIG, _pDM_Odm)
+=====================================*/
+
+#define _reg_11N(_name) ODM_REG_##_name##_11N
+#define _bit_11N(_name) ODM_BIT_##_name##_11N
+
+#define _cat(_name, _ic_type, _func) _func##_11N(_name)
+
+/* _name: name of register or bit. */
+/* Example: "ODM_REG(R_A_AGC_CORE1, pDM_Odm)" */
+/* gets "ODM_R_A_AGC_CORE1" or "ODM_R_A_AGC_CORE1_8192C", depends on SupportICType. */
+#define ODM_REG(_name, _pDM_Odm) _cat(_name, _pDM_Odm->SupportICType, _reg)
+#define ODM_BIT(_name, _pDM_Odm) _cat(_name, _pDM_Odm->SupportICType, _bit)
+
+#endif /* __ODM_INTERFACE_H__ */
diff --git a/drivers/staging/rtl8723bs/hal/odm_precomp.h b/drivers/staging/rtl8723bs/hal/odm_precomp.h
new file mode 100644
index 000000000..2987857a8
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/odm_precomp.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#ifndef __ODM_PRECOMP_H__
+#define __ODM_PRECOMP_H__
+
+#include "odm_types.h"
+
+#define TEST_FALG___ 1
+
+/* 2 Config Flags and Structs - defined by each ODM Type */
+
+ /* include <basic_types.h> */
+ /* include <osdep_service.h> */
+ /* include <drv_types.h> */
+ /* include <rtw_byteorder.h> */
+ /* include <hal_intf.h> */
+#define BEAMFORMING_SUPPORT 0
+
+/* 2 Hardware Parameter Files */
+
+/* 2 OutSrc Header Files */
+
+#include "odm.h"
+#include "odm_HWConfig.h"
+#include "odm_RegDefine11N.h"
+#include "odm_EdcaTurboCheck.h"
+#include "odm_DIG.h"
+#include "odm_DynamicBBPowerSaving.h"
+#include "odm_DynamicTxPower.h"
+#include "odm_CfoTracking.h"
+#include "HalPhyRf.h"
+#include "HalPhyRf_8723B.h"/* for IQK, LCK, Power-tracking */
+#include "rtl8723b_hal.h"
+#include "odm_interface.h"
+#include "odm_reg.h"
+#include "HalHWImg8723B_MAC.h"
+#include "HalHWImg8723B_RF.h"
+#include "HalHWImg8723B_BB.h"
+#include "Hal8723BReg.h"
+#include "odm_RegConfig8723B.h"
+
+#endif /* __ODM_PRECOMP_H__ */
diff --git a/drivers/staging/rtl8723bs/hal/odm_reg.h b/drivers/staging/rtl8723bs/hal/odm_reg.h
new file mode 100644
index 000000000..a3b1f6737
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/odm_reg.h
@@ -0,0 +1,91 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+/* File Name: odm_reg.h */
+/* Description: */
+/* This file is for general register definition. */
+#ifndef __HAL_ODM_REG_H__
+#define __HAL_ODM_REG_H__
+
+/* Register Definition */
+
+/* MAC REG */
+#define ODM_BB_RESET 0x002
+#define ODM_DUMMY 0x4fe
+#define RF_T_METER_OLD 0x24
+#define RF_T_METER_NEW 0x42
+
+#define ODM_EDCA_VO_PARAM 0x500
+#define ODM_EDCA_VI_PARAM 0x504
+#define ODM_EDCA_BE_PARAM 0x508
+#define ODM_EDCA_BK_PARAM 0x50C
+#define ODM_TXPAUSE 0x522
+
+/* BB REG */
+#define ODM_FPGA_PHY0_PAGE8 0x800
+#define ODM_PSD_SETTING 0x808
+#define ODM_AFE_SETTING 0x818
+#define ODM_TXAGC_B_24_54 0x834
+#define ODM_TXAGC_B_MCS32_5 0x838
+#define ODM_TXAGC_B_MCS0_MCS3 0x83c
+#define ODM_TXAGC_B_MCS4_MCS7 0x848
+#define ODM_ANALOG_REGISTER 0x85c
+#define ODM_RF_INTERFACE_OUTPUT 0x860
+#define ODM_TXAGC_B_11_A_2_11 0x86c
+#define ODM_AD_DA_LSB_MASK 0x874
+#define ODM_ENABLE_3_WIRE 0x88c
+#define ODM_PSD_REPORT 0x8b4
+#define ODM_R_ANT_SELECT 0x90c
+#define ODM_CCK_ANT_SELECT 0xa07
+#define ODM_CCK_PD_THRESH 0xa0a
+#define ODM_CCK_RF_REG1 0xa11
+#define ODM_CCK_MATCH_FILTER 0xa20
+#define ODM_CCK_RAKE_MAC 0xa2e
+#define ODM_CCK_CNT_RESET 0xa2d
+#define ODM_CCK_TX_DIVERSITY 0xa2f
+#define ODM_CCK_FA_CNT_MSB 0xa5b
+#define ODM_CCK_FA_CNT_LSB 0xa5c
+#define ODM_CCK_NEW_FUNCTION 0xa75
+#define ODM_OFDM_PHY0_PAGE_C 0xc00
+#define ODM_OFDM_RX_ANT 0xc04
+#define ODM_R_A_RXIQI 0xc14
+#define ODM_R_A_AGC_CORE1 0xc50
+#define ODM_R_A_AGC_CORE2 0xc54
+#define ODM_R_B_AGC_CORE1 0xc58
+#define ODM_R_AGC_PAR 0xc70
+#define ODM_R_HTSTF_AGC_PAR 0xc7c
+#define ODM_TX_PWR_TRAINING_A 0xc90
+#define ODM_TX_PWR_TRAINING_B 0xc98
+#define ODM_OFDM_FA_CNT1 0xcf0
+#define ODM_OFDM_PHY0_PAGE_D 0xd00
+#define ODM_OFDM_FA_CNT2 0xda0
+#define ODM_OFDM_FA_CNT3 0xda4
+#define ODM_OFDM_FA_CNT4 0xda8
+#define ODM_TXAGC_A_6_18 0xe00
+#define ODM_TXAGC_A_24_54 0xe04
+#define ODM_TXAGC_A_1_MCS32 0xe08
+#define ODM_TXAGC_A_MCS0_MCS3 0xe10
+#define ODM_TXAGC_A_MCS4_MCS7 0xe14
+
+/* RF REG */
+#define ODM_GAIN_SETTING 0x00
+#define ODM_CHANNEL 0x18
+
+/* Ant Detect Reg */
+#define ODM_DPDT 0x300
+
+/* PSD Init */
+#define ODM_PSDREG 0x808
+
+/* 92D Path Div */
+#define PATHDIV_REG 0xB30
+#define PATHDIV_TRI 0xBA0
+
+/* Bitmap Definition */
+
+#define BIT_FA_RESET BIT0
+
+#endif
diff --git a/drivers/staging/rtl8723bs/hal/odm_types.h b/drivers/staging/rtl8723bs/hal/odm_types.h
new file mode 100644
index 000000000..8168dc14e
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/odm_types.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __ODM_TYPES_H__
+#define __ODM_TYPES_H__
+
+#include <drv_types.h>
+
+/* Deifne HW endian support */
+#define ODM_ENDIAN_BIG 0
+#define ODM_ENDIAN_LITTLE 1
+
+#define GET_ODM(__padapter) ((PDM_ODM_T)(&((GET_HAL_DATA(__padapter))->odmpriv)))
+
+enum hal_status {
+ HAL_STATUS_SUCCESS,
+ HAL_STATUS_FAILURE,
+ /*RT_STATUS_PENDING,
+ RT_STATUS_RESOURCE,
+ RT_STATUS_INVALID_CONTEXT,
+ RT_STATUS_INVALID_PARAMETER,
+ RT_STATUS_NOT_SUPPORT,
+ RT_STATUS_OS_API_FAILED,*/
+};
+
+
+ #if defined(__LITTLE_ENDIAN)
+ #define ODM_ENDIAN_TYPE ODM_ENDIAN_LITTLE
+ #else
+ #define ODM_ENDIAN_TYPE ODM_ENDIAN_BIG
+ #endif
+
+ #define STA_INFO_T struct sta_info
+ #define PSTA_INFO_T struct sta_info *
+
+ #define SET_TX_DESC_ANTSEL_A_88E(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+8, 24, 1, __Value)
+ #define SET_TX_DESC_ANTSEL_B_88E(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+8, 25, 1, __Value)
+ #define SET_TX_DESC_ANTSEL_C_88E(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+28, 29, 1, __Value)
+
+ /* define useless flag to avoid compile warning */
+ #define USE_WORKITEM 0
+ #define FPGA_TWO_MAC_VERIFICATION 0
+
+#define READ_NEXT_PAIR(v1, v2, i) do { if (i+2 >= ArrayLen) break; i += 2; v1 = Array[i]; v2 = Array[i+1]; } while (0)
+#define COND_ELSE 2
+#define COND_ENDIF 3
+
+#endif /* __ODM_TYPES_H__ */
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c b/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c
new file mode 100644
index 000000000..a59ae622f
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c
@@ -0,0 +1,980 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include <drv_types.h>
+#include <rtw_debug.h>
+#include <rtl8723b_hal.h>
+#include "hal_com_h2c.h"
+
+#define MAX_H2C_BOX_NUMS 4
+#define MESSAGE_BOX_SIZE 4
+
+#define RTL8723B_MAX_CMD_LEN 7
+#define RTL8723B_EX_MESSAGE_BOX_SIZE 4
+
+static u8 _is_fw_read_cmd_down(struct adapter *padapter, u8 msgbox_num)
+{
+ u8 read_down = false;
+ int retry_cnts = 100;
+
+ u8 valid;
+
+ do {
+ valid = rtw_read8(padapter, REG_HMETFR) & BIT(msgbox_num);
+ if (0 == valid) {
+ read_down = true;
+ }
+ } while ((!read_down) && (retry_cnts--));
+
+ return read_down;
+
+}
+
+
+/*****************************************
+* H2C Msg format :
+*| 31 - 8 |7-5 | 4 - 0 |
+*| h2c_msg |Class |CMD_ID |
+*| 31-0 |
+*| Ext msg |
+*
+******************************************/
+s32 FillH2CCmd8723B(struct adapter *padapter, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer)
+{
+ u8 h2c_box_num;
+ u32 msgbox_addr;
+ u32 msgbox_ex_addr = 0;
+ struct hal_com_data *pHalData;
+ u32 h2c_cmd = 0;
+ u32 h2c_cmd_ex = 0;
+ s32 ret = _FAIL;
+
+ padapter = GET_PRIMARY_ADAPTER(padapter);
+ pHalData = GET_HAL_DATA(padapter);
+ if (mutex_lock_interruptible(&(adapter_to_dvobj(padapter)->h2c_fwcmd_mutex)))
+ return ret;
+
+ if (!pCmdBuffer) {
+ goto exit;
+ }
+
+ if (CmdLen > RTL8723B_MAX_CMD_LEN) {
+ goto exit;
+ }
+
+ if (padapter->bSurpriseRemoved)
+ goto exit;
+
+ /* pay attention to if race condition happened in H2C cmd setting. */
+ do {
+ h2c_box_num = pHalData->LastHMEBoxNum;
+
+ if (!_is_fw_read_cmd_down(padapter, h2c_box_num))
+ goto exit;
+
+ if (CmdLen <= 3)
+ memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer, CmdLen);
+ else {
+ memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer, 3);
+ memcpy((u8 *)(&h2c_cmd_ex), pCmdBuffer+3, CmdLen-3);
+/* *(u8 *)(&h2c_cmd) |= BIT(7); */
+ }
+
+ *(u8 *)(&h2c_cmd) |= ElementID;
+
+ if (CmdLen > 3) {
+ msgbox_ex_addr = REG_HMEBOX_EXT0_8723B + (h2c_box_num*RTL8723B_EX_MESSAGE_BOX_SIZE);
+ rtw_write32(padapter, msgbox_ex_addr, h2c_cmd_ex);
+ }
+ msgbox_addr = REG_HMEBOX_0 + (h2c_box_num*MESSAGE_BOX_SIZE);
+ rtw_write32(padapter, msgbox_addr, h2c_cmd);
+
+ pHalData->LastHMEBoxNum = (h2c_box_num+1) % MAX_H2C_BOX_NUMS;
+
+ } while (0);
+
+ ret = _SUCCESS;
+
+exit:
+
+ mutex_unlock(&(adapter_to_dvobj(padapter)->h2c_fwcmd_mutex));
+ return ret;
+}
+
+static void ConstructBeacon(struct adapter *padapter, u8 *pframe, u32 *pLength)
+{
+ struct ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ u32 rate_len, pktlen;
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+ struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network);
+
+ pwlanhdr = (struct ieee80211_hdr *)pframe;
+
+ fctrl = &(pwlanhdr->frame_control);
+ *(fctrl) = 0;
+
+ eth_broadcast_addr(pwlanhdr->addr1);
+ memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
+ memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
+
+ SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
+ /* pmlmeext->mgnt_seq++; */
+ SetFrameSubType(pframe, WIFI_BEACON);
+
+ pframe += sizeof(struct ieee80211_hdr_3addr);
+ pktlen = sizeof(struct ieee80211_hdr_3addr);
+
+ /* timestamp will be inserted by hardware */
+ pframe += 8;
+ pktlen += 8;
+
+ /* beacon interval: 2 bytes */
+ memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->ies)), 2);
+
+ pframe += 2;
+ pktlen += 2;
+
+ /* capability info: 2 bytes */
+ memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->ies)), 2);
+
+ pframe += 2;
+ pktlen += 2;
+
+ if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
+ pktlen += cur_network->ie_length - sizeof(struct ndis_802_11_fix_ie);
+ memcpy(pframe, cur_network->ies+sizeof(struct ndis_802_11_fix_ie), pktlen);
+
+ goto _ConstructBeacon;
+ }
+
+ /* below for ad-hoc mode */
+
+ /* SSID */
+ pframe = rtw_set_ie(pframe, WLAN_EID_SSID, cur_network->ssid.ssid_length, cur_network->ssid.ssid, &pktlen);
+
+ /* supported rates... */
+ rate_len = rtw_get_rateset_len(cur_network->supported_rates);
+ pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, ((rate_len > 8) ? 8 : rate_len), cur_network->supported_rates, &pktlen);
+
+ /* DS parameter set */
+ pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)&(cur_network->configuration.ds_config), &pktlen);
+
+ if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
+ u32 ATIMWindow;
+ /* IBSS Parameter Set... */
+ /* ATIMWindow = cur->configuration.ATIMWindow; */
+ ATIMWindow = 0;
+ pframe = rtw_set_ie(pframe, WLAN_EID_IBSS_PARAMS, 2, (unsigned char *)(&ATIMWindow), &pktlen);
+ }
+
+
+ /* todo: ERP IE */
+
+
+ /* EXTERNDED SUPPORTED RATE */
+ if (rate_len > 8)
+ pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (rate_len - 8), (cur_network->supported_rates + 8), &pktlen);
+
+
+ /* todo:HT for adhoc */
+
+_ConstructBeacon:
+
+ if ((pktlen + TXDESC_SIZE) > 512)
+ return;
+
+ *pLength = pktlen;
+
+}
+
+static void ConstructPSPoll(struct adapter *padapter, u8 *pframe, u32 *pLength)
+{
+ struct ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+
+ pwlanhdr = (struct ieee80211_hdr *)pframe;
+
+ /* Frame control. */
+ fctrl = &(pwlanhdr->frame_control);
+ *(fctrl) = 0;
+ SetPwrMgt(fctrl);
+ SetFrameSubType(pframe, WIFI_PSPOLL);
+
+ /* AID. */
+ SetDuration(pframe, (pmlmeinfo->aid | 0xc000));
+
+ /* BSSID. */
+ memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
+
+ /* TA. */
+ memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
+
+ *pLength = 16;
+}
+
+static void ConstructNullFunctionData(
+ struct adapter *padapter,
+ u8 *pframe,
+ u32 *pLength,
+ u8 *StaAddr,
+ u8 bQoS,
+ u8 AC,
+ u8 bEosp,
+ u8 bForcePowerSave
+)
+{
+ struct ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ u32 pktlen;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct wlan_network *cur_network = &pmlmepriv->cur_network;
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+
+ pwlanhdr = (struct ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_control;
+ *(fctrl) = 0;
+ if (bForcePowerSave)
+ SetPwrMgt(fctrl);
+
+ switch (cur_network->network.infrastructure_mode) {
+ case Ndis802_11Infrastructure:
+ SetToDs(fctrl);
+ memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
+ memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
+ memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN);
+ break;
+ case Ndis802_11APMode:
+ SetFrDs(fctrl);
+ memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
+ memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
+ break;
+ case Ndis802_11IBSS:
+ default:
+ memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
+ memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
+ break;
+ }
+
+ SetSeqNum(pwlanhdr, 0);
+
+ if (bQoS) {
+ struct ieee80211_qos_hdr *pwlanqoshdr;
+
+ SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
+
+ pwlanqoshdr = (struct ieee80211_qos_hdr *)pframe;
+ SetPriority(&pwlanqoshdr->qos_ctrl, AC);
+ SetEOSP(&pwlanqoshdr->qos_ctrl, bEosp);
+
+ pktlen = sizeof(struct ieee80211_qos_hdr);
+ } else {
+ SetFrameSubType(pframe, WIFI_DATA_NULL);
+
+ pktlen = sizeof(struct ieee80211_hdr_3addr);
+ }
+
+ *pLength = pktlen;
+}
+
+/*
+ * To check if reserved page content is destroyed by beacon because beacon
+ * is too large.
+ */
+/* 2010.06.23. Added by tynli. */
+void CheckFwRsvdPageContent(struct adapter *Adapter)
+{
+}
+
+static void rtl8723b_set_FwRsvdPage_cmd(struct adapter *padapter, struct rsvdpage_loc *rsvdpageloc)
+{
+ u8 u1H2CRsvdPageParm[H2C_RSVDPAGE_LOC_LEN] = {0};
+
+ SET_8723B_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1H2CRsvdPageParm, rsvdpageloc->LocProbeRsp);
+ SET_8723B_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1H2CRsvdPageParm, rsvdpageloc->LocPsPoll);
+ SET_8723B_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1H2CRsvdPageParm, rsvdpageloc->LocNullData);
+ SET_8723B_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1H2CRsvdPageParm, rsvdpageloc->LocQosNull);
+ SET_8723B_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1H2CRsvdPageParm, rsvdpageloc->LocBTQosNull);
+
+ FillH2CCmd8723B(padapter, H2C_8723B_RSVD_PAGE, H2C_RSVDPAGE_LOC_LEN, u1H2CRsvdPageParm);
+}
+
+static void rtl8723b_set_FwAoacRsvdPage_cmd(struct adapter *padapter, struct rsvdpage_loc *rsvdpageloc)
+{
+}
+
+void rtl8723b_set_FwMediaStatusRpt_cmd(struct adapter *padapter, u8 mstatus, u8 macid)
+{
+ u8 u1H2CMediaStatusRptParm[H2C_MEDIA_STATUS_RPT_LEN] = {0};
+ u8 macid_end = 0;
+
+ SET_8723B_H2CCMD_MSRRPT_PARM_OPMODE(u1H2CMediaStatusRptParm, mstatus);
+ SET_8723B_H2CCMD_MSRRPT_PARM_MACID_IND(u1H2CMediaStatusRptParm, 0);
+ SET_8723B_H2CCMD_MSRRPT_PARM_MACID(u1H2CMediaStatusRptParm, macid);
+ SET_8723B_H2CCMD_MSRRPT_PARM_MACID_END(u1H2CMediaStatusRptParm, macid_end);
+
+ FillH2CCmd8723B(padapter, H2C_8723B_MEDIA_STATUS_RPT, H2C_MEDIA_STATUS_RPT_LEN, u1H2CMediaStatusRptParm);
+}
+
+void rtl8723b_set_FwMacIdConfig_cmd(struct adapter *padapter, u8 mac_id, u8 raid, u8 bw, u8 sgi, u32 mask)
+{
+ u8 u1H2CMacIdConfigParm[H2C_MACID_CFG_LEN] = {0};
+
+ SET_8723B_H2CCMD_MACID_CFG_MACID(u1H2CMacIdConfigParm, mac_id);
+ SET_8723B_H2CCMD_MACID_CFG_RAID(u1H2CMacIdConfigParm, raid);
+ SET_8723B_H2CCMD_MACID_CFG_SGI_EN(u1H2CMacIdConfigParm, sgi ? 1 : 0);
+ SET_8723B_H2CCMD_MACID_CFG_BW(u1H2CMacIdConfigParm, bw);
+ SET_8723B_H2CCMD_MACID_CFG_RATE_MASK0(u1H2CMacIdConfigParm, (u8)(mask & 0x000000ff));
+ SET_8723B_H2CCMD_MACID_CFG_RATE_MASK1(u1H2CMacIdConfigParm, (u8)((mask & 0x0000ff00) >> 8));
+ SET_8723B_H2CCMD_MACID_CFG_RATE_MASK2(u1H2CMacIdConfigParm, (u8)((mask & 0x00ff0000) >> 16));
+ SET_8723B_H2CCMD_MACID_CFG_RATE_MASK3(u1H2CMacIdConfigParm, (u8)((mask & 0xff000000) >> 24));
+
+ FillH2CCmd8723B(padapter, H2C_8723B_MACID_CFG, H2C_MACID_CFG_LEN, u1H2CMacIdConfigParm);
+}
+
+void rtl8723b_set_rssi_cmd(struct adapter *padapter, u8 *param)
+{
+ u8 u1H2CRssiSettingParm[H2C_RSSI_SETTING_LEN] = {0};
+ u8 mac_id = *param;
+ u8 rssi = *(param+2);
+ u8 uldl_state = 0;
+
+ SET_8723B_H2CCMD_RSSI_SETTING_MACID(u1H2CRssiSettingParm, mac_id);
+ SET_8723B_H2CCMD_RSSI_SETTING_RSSI(u1H2CRssiSettingParm, rssi);
+ SET_8723B_H2CCMD_RSSI_SETTING_ULDL_STATE(u1H2CRssiSettingParm, uldl_state);
+
+ FillH2CCmd8723B(padapter, H2C_8723B_RSSI_SETTING, H2C_RSSI_SETTING_LEN, u1H2CRssiSettingParm);
+}
+
+void rtl8723b_set_FwPwrMode_cmd(struct adapter *padapter, u8 psmode)
+{
+ int i;
+ struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ u8 u1H2CPwrModeParm[H2C_PWRMODE_LEN] = {0};
+ u8 PowerState = 0, awake_intvl = 1, byte5 = 0, rlbm = 0;
+
+ if (pwrpriv->dtim > 0 && pwrpriv->dtim < 16)
+ awake_intvl = pwrpriv->dtim+1;/* DTIM = (awake_intvl - 1) */
+ else
+ awake_intvl = 3;/* DTIM =2 */
+
+ rlbm = 2;
+
+ if (padapter->registrypriv.wifi_spec == 1) {
+ awake_intvl = 2;
+ rlbm = 2;
+ }
+
+ if (psmode > 0) {
+ if (hal_btcoex_IsBtControlLps(padapter) == true) {
+ PowerState = hal_btcoex_RpwmVal(padapter);
+ byte5 = hal_btcoex_LpsVal(padapter);
+
+ if ((rlbm == 2) && (byte5 & BIT(4))) {
+ /* Keep awake interval to 1 to prevent from */
+ /* decreasing coex performance */
+ awake_intvl = 2;
+ rlbm = 2;
+ }
+ } else {
+ PowerState = 0x00;/* AllON(0x0C), RFON(0x04), RFOFF(0x00) */
+ byte5 = 0x40;
+ }
+ } else {
+ PowerState = 0x0C;/* AllON(0x0C), RFON(0x04), RFOFF(0x00) */
+ byte5 = 0x40;
+ }
+
+ SET_8723B_H2CCMD_PWRMODE_PARM_MODE(u1H2CPwrModeParm, (psmode > 0) ? 1 : 0);
+ SET_8723B_H2CCMD_PWRMODE_PARM_SMART_PS(u1H2CPwrModeParm, pwrpriv->smart_ps);
+ SET_8723B_H2CCMD_PWRMODE_PARM_RLBM(u1H2CPwrModeParm, rlbm);
+ SET_8723B_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1H2CPwrModeParm, awake_intvl);
+ SET_8723B_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1H2CPwrModeParm, padapter->registrypriv.uapsd_enable);
+ SET_8723B_H2CCMD_PWRMODE_PARM_PWR_STATE(u1H2CPwrModeParm, PowerState);
+ SET_8723B_H2CCMD_PWRMODE_PARM_BYTE5(u1H2CPwrModeParm, byte5);
+ if (psmode != PS_MODE_ACTIVE) {
+ if (!pmlmeext->adaptive_tsf_done && pmlmeext->bcn_cnt > 0) {
+ u8 ratio_20_delay, ratio_80_delay;
+
+ /* byte 6 for adaptive_early_32k */
+ /* 0:3] = DrvBcnEarly (ms) , [4:7] = DrvBcnTimeOut (ms) */
+ /* 20% for DrvBcnEarly, 80% for DrvBcnTimeOut */
+ ratio_20_delay = 0;
+ ratio_80_delay = 0;
+ pmlmeext->DrvBcnEarly = 0xff;
+ pmlmeext->DrvBcnTimeOut = 0xff;
+
+ for (i = 0; i < 9; i++) {
+ pmlmeext->bcn_delay_ratio[i] = (pmlmeext->bcn_delay_cnt[i]*100)/pmlmeext->bcn_cnt;
+
+ ratio_20_delay += pmlmeext->bcn_delay_ratio[i];
+ ratio_80_delay += pmlmeext->bcn_delay_ratio[i];
+
+ if (ratio_20_delay > 20 && pmlmeext->DrvBcnEarly == 0xff)
+ pmlmeext->DrvBcnEarly = i;
+
+ if (ratio_80_delay > 80 && pmlmeext->DrvBcnTimeOut == 0xff)
+ pmlmeext->DrvBcnTimeOut = i;
+
+ /* reset adaptive_early_32k cnt */
+ pmlmeext->bcn_delay_cnt[i] = 0;
+ pmlmeext->bcn_delay_ratio[i] = 0;
+
+ }
+
+ pmlmeext->bcn_cnt = 0;
+ pmlmeext->adaptive_tsf_done = true;
+
+ }
+
+/* offload to FW if fw version > v15.10
+ pmlmeext->DrvBcnEarly = 0;
+ pmlmeext->DrvBcnTimeOut =7;
+
+ if ((pmlmeext->DrvBcnEarly!= 0Xff) && (pmlmeext->DrvBcnTimeOut!= 0xff))
+ u1H2CPwrModeParm[H2C_PWRMODE_LEN-1] = BIT(0) | ((pmlmeext->DrvBcnEarly<<1)&0x0E) |((pmlmeext->DrvBcnTimeOut<<4)&0xf0) ;
+*/
+
+ }
+
+ hal_btcoex_RecordPwrMode(padapter, u1H2CPwrModeParm, H2C_PWRMODE_LEN);
+
+ FillH2CCmd8723B(padapter, H2C_8723B_SET_PWR_MODE, H2C_PWRMODE_LEN, u1H2CPwrModeParm);
+}
+
+void rtl8723b_set_FwPsTuneParam_cmd(struct adapter *padapter)
+{
+ u8 u1H2CPsTuneParm[H2C_PSTUNEPARAM_LEN] = {0};
+ u8 bcn_to_limit = 10; /* 10 * 100 * awakeinterval (ms) */
+ u8 dtim_timeout = 5; /* ms wait broadcast data timer */
+ u8 ps_timeout = 20; /* ms Keep awake when tx */
+ u8 dtim_period = 3;
+
+ SET_8723B_H2CCMD_PSTUNE_PARM_BCN_TO_LIMIT(u1H2CPsTuneParm, bcn_to_limit);
+ SET_8723B_H2CCMD_PSTUNE_PARM_DTIM_TIMEOUT(u1H2CPsTuneParm, dtim_timeout);
+ SET_8723B_H2CCMD_PSTUNE_PARM_PS_TIMEOUT(u1H2CPsTuneParm, ps_timeout);
+ SET_8723B_H2CCMD_PSTUNE_PARM_ADOPT(u1H2CPsTuneParm, 1);
+ SET_8723B_H2CCMD_PSTUNE_PARM_DTIM_PERIOD(u1H2CPsTuneParm, dtim_period);
+
+ FillH2CCmd8723B(padapter, H2C_8723B_PS_TUNING_PARA, H2C_PSTUNEPARAM_LEN, u1H2CPsTuneParm);
+}
+
+void rtl8723b_set_FwPwrModeInIPS_cmd(struct adapter *padapter, u8 cmd_param)
+{
+
+ FillH2CCmd8723B(padapter, H2C_8723B_FWLPS_IN_IPS_, 1, &cmd_param);
+}
+
+/*
+ * Description: Fill the reserved packets that FW will use to RSVD page.
+ * Now we just send 4 types packet to rsvd page.
+ * (1)Beacon, (2)Ps-poll, (3)Null data, (4)ProbeRsp.
+ *
+ * Input:
+ *
+ * bDLFinished - false: At the first time we will send all the packets as
+ * a large packet to Hw, so we need to set the packet length to total length.
+ *
+ * true: At the second time, we should send the first packet (default:beacon)
+ * to Hw again and set the length in descriptor to the real beacon length.
+ */
+/* 2009.10.15 by tynli. */
+static void rtl8723b_set_FwRsvdPagePkt(
+ struct adapter *padapter, bool bDLFinished
+)
+{
+ struct xmit_frame *pcmdframe;
+ struct pkt_attrib *pattrib;
+ struct xmit_priv *pxmitpriv;
+ struct mlme_ext_priv *pmlmeext;
+ struct mlme_ext_info *pmlmeinfo;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ u32 BeaconLength = 0, PSPollLength = 0;
+ u32 NullDataLength = 0, QosNullLength = 0, BTQosNullLength = 0;
+ u8 *ReservedPagePacket;
+ u8 TxDescLen = TXDESC_SIZE, TxDescOffset = TXDESC_OFFSET;
+ u8 TotalPageNum = 0, CurtPktPageNum = 0, RsvdPageNum = 0;
+ u16 BufIndex, PageSize = 128;
+ u32 TotalPacketLen, MaxRsvdPageBufSize = 0;
+
+ struct rsvdpage_loc RsvdPageLoc;
+
+ pxmitpriv = &padapter->xmitpriv;
+ pmlmeext = &padapter->mlmeextpriv;
+ pmlmeinfo = &pmlmeext->mlmext_info;
+
+ RsvdPageNum = BCNQ_PAGE_NUM_8723B + WOWLAN_PAGE_NUM_8723B;
+ MaxRsvdPageBufSize = RsvdPageNum*PageSize;
+
+ pcmdframe = rtw_alloc_cmdxmitframe(pxmitpriv);
+ if (!pcmdframe)
+ return;
+
+ ReservedPagePacket = pcmdframe->buf_addr;
+ memset(&RsvdPageLoc, 0, sizeof(struct rsvdpage_loc));
+
+ /* 3 (1) beacon */
+ BufIndex = TxDescOffset;
+ ConstructBeacon(padapter, &ReservedPagePacket[BufIndex], &BeaconLength);
+
+ /* When we count the first page size, we need to reserve description size for the RSVD */
+ /* packet, it will be filled in front of the packet in TXPKTBUF. */
+ CurtPktPageNum = (u8)PageNum_128(TxDescLen + BeaconLength);
+ /* If we don't add 1 more page, the WOWLAN function has a problem. Baron thinks it's a bug of firmware */
+ if (CurtPktPageNum == 1)
+ CurtPktPageNum += 1;
+
+ TotalPageNum += CurtPktPageNum;
+
+ BufIndex += (CurtPktPageNum*PageSize);
+
+ /* 3 (2) ps-poll */
+ RsvdPageLoc.LocPsPoll = TotalPageNum;
+ ConstructPSPoll(padapter, &ReservedPagePacket[BufIndex], &PSPollLength);
+ rtl8723b_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], PSPollLength, true, false, false);
+
+ CurtPktPageNum = (u8)PageNum_128(TxDescLen + PSPollLength);
+
+ TotalPageNum += CurtPktPageNum;
+
+ BufIndex += (CurtPktPageNum*PageSize);
+
+ /* 3 (3) null data */
+ RsvdPageLoc.LocNullData = TotalPageNum;
+ ConstructNullFunctionData(
+ padapter,
+ &ReservedPagePacket[BufIndex],
+ &NullDataLength,
+ get_my_bssid(&pmlmeinfo->network),
+ false, 0, 0, false
+ );
+ rtl8723b_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], NullDataLength, false, false, false);
+
+ CurtPktPageNum = (u8)PageNum_128(TxDescLen + NullDataLength);
+
+ TotalPageNum += CurtPktPageNum;
+
+ BufIndex += (CurtPktPageNum*PageSize);
+
+ /* 3 (5) Qos null data */
+ RsvdPageLoc.LocQosNull = TotalPageNum;
+ ConstructNullFunctionData(
+ padapter,
+ &ReservedPagePacket[BufIndex],
+ &QosNullLength,
+ get_my_bssid(&pmlmeinfo->network),
+ true, 0, 0, false
+ );
+ rtl8723b_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], QosNullLength, false, false, false);
+
+ CurtPktPageNum = (u8)PageNum_128(TxDescLen + QosNullLength);
+
+ TotalPageNum += CurtPktPageNum;
+
+ BufIndex += (CurtPktPageNum*PageSize);
+
+ /* 3 (6) BT Qos null data */
+ RsvdPageLoc.LocBTQosNull = TotalPageNum;
+ ConstructNullFunctionData(
+ padapter,
+ &ReservedPagePacket[BufIndex],
+ &BTQosNullLength,
+ get_my_bssid(&pmlmeinfo->network),
+ true, 0, 0, false
+ );
+ rtl8723b_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true, false);
+
+ CurtPktPageNum = (u8)PageNum_128(TxDescLen + BTQosNullLength);
+
+ TotalPageNum += CurtPktPageNum;
+
+ BufIndex += (CurtPktPageNum*PageSize);
+
+ TotalPacketLen = BufIndex + BTQosNullLength;
+
+ if (TotalPacketLen > MaxRsvdPageBufSize) {
+ goto error;
+ } else {
+ /* update attribute */
+ pattrib = &pcmdframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+ pattrib->qsel = 0x10;
+ pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TxDescOffset;
+ dump_mgntframe_and_wait(padapter, pcmdframe, 100);
+ }
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ rtl8723b_set_FwRsvdPage_cmd(padapter, &RsvdPageLoc);
+ rtl8723b_set_FwAoacRsvdPage_cmd(padapter, &RsvdPageLoc);
+ } else {
+ rtl8723b_set_FwAoacRsvdPage_cmd(padapter, &RsvdPageLoc);
+ }
+ return;
+
+error:
+
+ rtw_free_xmitframe(pxmitpriv, pcmdframe);
+}
+
+void rtl8723b_download_rsvd_page(struct adapter *padapter, u8 mstatus)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+ bool bcn_valid = false;
+ u8 DLBcnCount = 0;
+ u32 poll = 0;
+ u8 val8;
+
+ if (mstatus == RT_MEDIA_CONNECT) {
+ bool bRecover = false;
+ u8 v8;
+
+ /* We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C. */
+ /* Suggested by filen. Added by tynli. */
+ rtw_write16(padapter, REG_BCN_PSR_RPT, (0xC000|pmlmeinfo->aid));
+
+ /* set REG_CR bit 8 */
+ v8 = rtw_read8(padapter, REG_CR+1);
+ v8 |= BIT(0); /* ENSWBCN */
+ rtw_write8(padapter, REG_CR+1, v8);
+
+ /* Disable Hw protection for a time which revserd for Hw sending beacon. */
+ /* Fix download reserved page packet fail that access collision with the protection time. */
+ /* 2010.05.11. Added by tynli. */
+ val8 = rtw_read8(padapter, REG_BCN_CTRL);
+ val8 &= ~EN_BCN_FUNCTION;
+ val8 |= DIS_TSF_UDT;
+ rtw_write8(padapter, REG_BCN_CTRL, val8);
+
+ /* Set FWHW_TXQ_CTRL 0x422[6]= 0 to tell Hw the packet is not a real beacon frame. */
+ if (pHalData->RegFwHwTxQCtrl & BIT(6))
+ bRecover = true;
+
+ /* To tell Hw the packet is not a real beacon frame. */
+ rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl & ~BIT(6));
+ pHalData->RegFwHwTxQCtrl &= ~BIT(6);
+
+ /* Clear beacon valid check bit. */
+ rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
+ rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL);
+
+ DLBcnCount = 0;
+ poll = 0;
+ do {
+ /* download rsvd page. */
+ rtl8723b_set_FwRsvdPagePkt(padapter, 0);
+ DLBcnCount++;
+ do {
+ yield();
+ /* mdelay(10); */
+ /* check rsvd page download OK. */
+ rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bcn_valid));
+ poll++;
+ } while (!bcn_valid && (poll%10) != 0 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
+
+ } while (!bcn_valid && DLBcnCount <= 100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
+
+ if (padapter->bSurpriseRemoved || padapter->bDriverStopped) {
+ } else {
+ struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
+ pwrctl->fw_psmode_iface_id = padapter->iface_id;
+ }
+
+ /* 2010.05.11. Added by tynli. */
+ val8 = rtw_read8(padapter, REG_BCN_CTRL);
+ val8 |= EN_BCN_FUNCTION;
+ val8 &= ~DIS_TSF_UDT;
+ rtw_write8(padapter, REG_BCN_CTRL, val8);
+
+ /* To make sure that if there exists an adapter which would like to send beacon. */
+ /* If exists, the origianl value of 0x422[6] will be 1, we should check this to */
+ /* prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */
+ /* the beacon cannot be sent by HW. */
+ /* 2010.06.23. Added by tynli. */
+ if (bRecover) {
+ rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl | BIT(6));
+ pHalData->RegFwHwTxQCtrl |= BIT(6);
+ }
+
+ /* Clear CR[8] or beacon packet will not be send to TxBuf anymore. */
+ v8 = rtw_read8(padapter, REG_CR+1);
+ v8 &= ~BIT(0); /* ~ENSWBCN */
+ rtw_write8(padapter, REG_CR+1, v8);
+ }
+}
+
+void rtl8723b_set_FwJoinBssRpt_cmd(struct adapter *padapter, u8 mstatus)
+{
+ if (mstatus == 1)
+ rtl8723b_download_rsvd_page(padapter, RT_MEDIA_CONNECT);
+}
+
+/* arg[0] = macid */
+/* arg[1] = raid */
+/* arg[2] = shortGIrate */
+/* arg[3] = init_rate */
+void rtl8723b_Add_RateATid(
+ struct adapter *padapter,
+ u32 bitmap,
+ u8 *arg,
+ u8 rssi_level
+)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+ struct sta_info *psta;
+ u8 mac_id = arg[0];
+ u8 raid = arg[1];
+ u8 shortGI = arg[2];
+ u8 bw;
+ u32 mask = bitmap&0x0FFFFFFF;
+
+ psta = pmlmeinfo->FW_sta_info[mac_id].psta;
+ if (!psta)
+ return;
+
+ bw = psta->bw_mode;
+
+ if (rssi_level != DM_RATR_STA_INIT)
+ mask = ODM_Get_Rate_Bitmap(&pHalData->odmpriv, mac_id, mask, rssi_level);
+
+ rtl8723b_set_FwMacIdConfig_cmd(padapter, mac_id, raid, bw, shortGI, mask);
+}
+
+static void ConstructBtNullFunctionData(
+ struct adapter *padapter,
+ u8 *pframe,
+ u32 *pLength,
+ u8 *StaAddr,
+ u8 bQoS,
+ u8 AC,
+ u8 bEosp,
+ u8 bForcePowerSave
+)
+{
+ struct ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ u32 pktlen;
+ u8 bssid[ETH_ALEN];
+
+ pwlanhdr = (struct ieee80211_hdr *)pframe;
+
+ if (!StaAddr) {
+ memcpy(bssid, myid(&padapter->eeprompriv), ETH_ALEN);
+ StaAddr = bssid;
+ }
+
+ fctrl = &pwlanhdr->frame_control;
+ *fctrl = 0;
+ if (bForcePowerSave)
+ SetPwrMgt(fctrl);
+
+ SetFrDs(fctrl);
+ memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
+ memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN);
+
+ SetDuration(pwlanhdr, 0);
+ SetSeqNum(pwlanhdr, 0);
+
+ if (bQoS) {
+ struct ieee80211_qos_hdr *pwlanqoshdr;
+
+ SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
+
+ pwlanqoshdr = (struct ieee80211_qos_hdr *)pframe;
+ SetPriority(&pwlanqoshdr->qos_ctrl, AC);
+ SetEOSP(&pwlanqoshdr->qos_ctrl, bEosp);
+
+ pktlen = sizeof(struct ieee80211_qos_hdr);
+ } else {
+ SetFrameSubType(pframe, WIFI_DATA_NULL);
+
+ pktlen = sizeof(struct ieee80211_hdr_3addr);
+ }
+
+ *pLength = pktlen;
+}
+
+static void SetFwRsvdPagePkt_BTCoex(struct adapter *padapter)
+{
+ struct xmit_frame *pcmdframe;
+ struct pkt_attrib *pattrib;
+ struct xmit_priv *pxmitpriv;
+ u32 BeaconLength = 0;
+ u32 BTQosNullLength = 0;
+ u8 *ReservedPagePacket;
+ u8 TxDescLen, TxDescOffset;
+ u8 TotalPageNum = 0, CurtPktPageNum = 0, RsvdPageNum = 0;
+ u16 BufIndex, PageSize;
+ u32 TotalPacketLen, MaxRsvdPageBufSize = 0;
+ struct rsvdpage_loc RsvdPageLoc;
+
+ pxmitpriv = &padapter->xmitpriv;
+ TxDescLen = TXDESC_SIZE;
+ TxDescOffset = TXDESC_OFFSET;
+ PageSize = PAGE_SIZE_TX_8723B;
+
+ RsvdPageNum = BCNQ_PAGE_NUM_8723B;
+ MaxRsvdPageBufSize = RsvdPageNum*PageSize;
+
+ pcmdframe = rtw_alloc_cmdxmitframe(pxmitpriv);
+ if (!pcmdframe)
+ return;
+
+ ReservedPagePacket = pcmdframe->buf_addr;
+ memset(&RsvdPageLoc, 0, sizeof(struct rsvdpage_loc));
+
+ /* 3 (1) beacon */
+ BufIndex = TxDescOffset;
+ ConstructBeacon(padapter, &ReservedPagePacket[BufIndex], &BeaconLength);
+
+ /* When we count the first page size, we need to reserve description size for the RSVD */
+ /* packet, it will be filled in front of the packet in TXPKTBUF. */
+ CurtPktPageNum = (u8)PageNum_128(TxDescLen + BeaconLength);
+ /* If we don't add 1 more page, the WOWLAN function has a problem. Baron thinks it's a bug of firmware */
+ if (CurtPktPageNum == 1)
+ CurtPktPageNum += 1;
+ TotalPageNum += CurtPktPageNum;
+
+ BufIndex += (CurtPktPageNum*PageSize);
+
+ /* Jump to lastest page */
+ if (BufIndex < (MaxRsvdPageBufSize - PageSize)) {
+ BufIndex = TxDescOffset + (MaxRsvdPageBufSize - PageSize);
+ TotalPageNum = BCNQ_PAGE_NUM_8723B - 1;
+ }
+
+ /* 3 (6) BT Qos null data */
+ RsvdPageLoc.LocBTQosNull = TotalPageNum;
+ ConstructBtNullFunctionData(
+ padapter,
+ &ReservedPagePacket[BufIndex],
+ &BTQosNullLength,
+ NULL,
+ true, 0, 0, false
+ );
+ rtl8723b_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true, false);
+
+ CurtPktPageNum = (u8)PageNum_128(TxDescLen + BTQosNullLength);
+
+ TotalPageNum += CurtPktPageNum;
+
+ TotalPacketLen = BufIndex + BTQosNullLength;
+ if (TotalPacketLen > MaxRsvdPageBufSize)
+ goto error;
+
+ /* update attribute */
+ pattrib = &pcmdframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+ pattrib->qsel = 0x10;
+ pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TxDescOffset;
+ dump_mgntframe_and_wait(padapter, pcmdframe, 100);
+
+ rtl8723b_set_FwRsvdPage_cmd(padapter, &RsvdPageLoc);
+ rtl8723b_set_FwAoacRsvdPage_cmd(padapter, &RsvdPageLoc);
+
+ return;
+
+error:
+ rtw_free_xmitframe(pxmitpriv, pcmdframe);
+}
+
+void rtl8723b_download_BTCoex_AP_mode_rsvd_page(struct adapter *padapter)
+{
+ struct hal_com_data *pHalData;
+ struct mlme_ext_priv *pmlmeext;
+ struct mlme_ext_info *pmlmeinfo;
+ u8 bRecover = false;
+ u8 bcn_valid = false;
+ u8 DLBcnCount = 0;
+ u32 poll = 0;
+ u8 val8;
+
+ pHalData = GET_HAL_DATA(padapter);
+ pmlmeext = &padapter->mlmeextpriv;
+ pmlmeinfo = &pmlmeext->mlmext_info;
+
+ /* We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C. */
+ /* Suggested by filen. Added by tynli. */
+ rtw_write16(padapter, REG_BCN_PSR_RPT, (0xC000|pmlmeinfo->aid));
+
+ /* set REG_CR bit 8 */
+ val8 = rtw_read8(padapter, REG_CR+1);
+ val8 |= BIT(0); /* ENSWBCN */
+ rtw_write8(padapter, REG_CR+1, val8);
+
+ /* Disable Hw protection for a time which revserd for Hw sending beacon. */
+ /* Fix download reserved page packet fail that access collision with the protection time. */
+ /* 2010.05.11. Added by tynli. */
+ val8 = rtw_read8(padapter, REG_BCN_CTRL);
+ val8 &= ~EN_BCN_FUNCTION;
+ val8 |= DIS_TSF_UDT;
+ rtw_write8(padapter, REG_BCN_CTRL, val8);
+
+ /* Set FWHW_TXQ_CTRL 0x422[6]= 0 to tell Hw the packet is not a real beacon frame. */
+ if (pHalData->RegFwHwTxQCtrl & BIT(6))
+ bRecover = true;
+
+ /* To tell Hw the packet is not a real beacon frame. */
+ pHalData->RegFwHwTxQCtrl &= ~BIT(6);
+ rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl);
+
+ /* Clear beacon valid check bit. */
+ rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
+ rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL);
+
+ DLBcnCount = 0;
+ poll = 0;
+ do {
+ SetFwRsvdPagePkt_BTCoex(padapter);
+ DLBcnCount++;
+ do {
+ yield();
+/* mdelay(10); */
+ /* check rsvd page download OK. */
+ rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, &bcn_valid);
+ poll++;
+ } while (!bcn_valid && (poll%10) != 0 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
+ } while (!bcn_valid && (DLBcnCount <= 100) && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
+
+ if (bcn_valid) {
+ struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
+ pwrctl->fw_psmode_iface_id = padapter->iface_id;
+ }
+
+ /* 2010.05.11. Added by tynli. */
+ val8 = rtw_read8(padapter, REG_BCN_CTRL);
+ val8 |= EN_BCN_FUNCTION;
+ val8 &= ~DIS_TSF_UDT;
+ rtw_write8(padapter, REG_BCN_CTRL, val8);
+
+ /* To make sure that if there exists an adapter which would like to send beacon. */
+ /* If exists, the origianl value of 0x422[6] will be 1, we should check this to */
+ /* prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */
+ /* the beacon cannot be sent by HW. */
+ /* 2010.06.23. Added by tynli. */
+ if (bRecover) {
+ pHalData->RegFwHwTxQCtrl |= BIT(6);
+ rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl);
+ }
+
+ /* Clear CR[8] or beacon packet will not be send to TxBuf anymore. */
+ val8 = rtw_read8(padapter, REG_CR+1);
+ val8 &= ~BIT(0); /* ~ENSWBCN */
+ rtw_write8(padapter, REG_CR+1, val8);
+}
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_dm.c b/drivers/staging/rtl8723bs/hal/rtl8723b_dm.c
new file mode 100644
index 000000000..202879198
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/rtl8723b_dm.c
@@ -0,0 +1,272 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+/* Description: */
+/* This file is for 92CE/92CU dynamic mechanism only */
+
+#include <drv_types.h>
+#include <rtw_debug.h>
+#include <rtl8723b_hal.h>
+
+/* Global var */
+
+static void dm_CheckStatistics(struct adapter *Adapter)
+{
+}
+/* */
+/* functions */
+/* */
+static void Init_ODM_ComInfo_8723b(struct adapter *Adapter)
+{
+
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+ struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
+ struct dm_priv *pdmpriv = &pHalData->dmpriv;
+ u8 cut_ver, fab_ver;
+
+ /* */
+ /* Init Value */
+ /* */
+ memset(pDM_Odm, 0, sizeof(*pDM_Odm));
+
+ pDM_Odm->Adapter = Adapter;
+#define ODM_CE 0x04
+ ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_PLATFORM, ODM_CE);
+ ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_INTERFACE, RTW_SDIO);
+ ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_PACKAGE_TYPE, pHalData->PackageType);
+ ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_IC_TYPE, ODM_RTL8723B);
+
+ fab_ver = ODM_TSMC;
+ cut_ver = ODM_CUT_A;
+
+ ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_FAB_VER, fab_ver);
+ ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_CUT_VER, cut_ver);
+
+ ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_PATCH_ID, pHalData->CustomerID);
+ /* ODM_CMNINFO_BINHCT_TEST only for MP Team */
+ ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_BWIFI_TEST, Adapter->registrypriv.wifi_spec);
+
+ pdmpriv->InitODMFlag = ODM_RF_CALIBRATION|ODM_RF_TX_PWR_TRACK;
+
+ ODM_CmnInfoUpdate(pDM_Odm, ODM_CMNINFO_ABILITY, pdmpriv->InitODMFlag);
+}
+
+static void Update_ODM_ComInfo_8723b(struct adapter *Adapter)
+{
+ struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
+ struct mlme_priv *pmlmepriv = &Adapter->mlmepriv;
+ struct dvobj_priv *dvobj = adapter_to_dvobj(Adapter);
+ struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(Adapter);
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+ struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
+ struct dm_priv *pdmpriv = &pHalData->dmpriv;
+ int i;
+ u8 zero = 0;
+
+ pdmpriv->InitODMFlag = 0
+ | ODM_BB_DIG
+ | ODM_BB_RA_MASK
+ | ODM_BB_DYNAMIC_TXPWR
+ | ODM_BB_FA_CNT
+ | ODM_BB_RSSI_MONITOR
+ | ODM_BB_CCK_PD
+ | ODM_BB_PWR_SAVE
+ | ODM_BB_CFO_TRACKING
+ | ODM_MAC_EDCA_TURBO
+ | ODM_RF_TX_PWR_TRACK
+ | ODM_RF_CALIBRATION
+ ;
+
+ /* */
+ /* Pointer reference */
+ /* */
+ /* ODM_CMNINFO_MAC_PHY_MODE pHalData->MacPhyMode92D */
+ /* ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_MAC_PHY_MODE,&(pDM_Odm->u8_temp)); */
+
+ ODM_CmnInfoUpdate(pDM_Odm, ODM_CMNINFO_ABILITY, pdmpriv->InitODMFlag);
+
+ ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_TX_UNI, &(dvobj->traffic_stat.tx_bytes));
+ ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_RX_UNI, &(dvobj->traffic_stat.rx_bytes));
+ ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_WM_MODE, &(pmlmeext->cur_wireless_mode));
+ ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_SEC_CHNL_OFFSET, &(pHalData->nCur40MhzPrimeSC));
+ ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_SEC_MODE, &(Adapter->securitypriv.dot11PrivacyAlgrthm));
+ ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_BW, &(pHalData->CurrentChannelBW));
+ ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_CHNL, &(pHalData->CurrentChannel));
+ ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_NET_CLOSED, &(Adapter->net_closed));
+ ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_MP_MODE, &zero);
+ ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_FORCED_IGI_LB, &(pHalData->u1ForcedIgiLb));
+ ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_FORCED_RATE, &(pHalData->ForcedDataRate));
+
+ ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_SCAN, &(pmlmepriv->bScanInProcess));
+ ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_POWER_SAVING, &(pwrctrlpriv->bpower_saving));
+
+
+ for (i = 0; i < NUM_STA; i++)
+ ODM_CmnInfoPtrArrayHook(pDM_Odm, ODM_CMNINFO_STA_STATUS, i, NULL);
+}
+
+void rtl8723b_InitHalDm(struct adapter *Adapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+ struct dm_priv *pdmpriv = &pHalData->dmpriv;
+ struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
+
+ pdmpriv->DM_Type = DM_Type_ByDriver;
+ pdmpriv->DMFlag = DYNAMIC_FUNC_DISABLE;
+
+ pdmpriv->DMFlag |= DYNAMIC_FUNC_BT;
+
+ pdmpriv->InitDMFlag = pdmpriv->DMFlag;
+
+ Update_ODM_ComInfo_8723b(Adapter);
+
+ ODM_DMInit(pDM_Odm);
+}
+
+void rtl8723b_HalDmWatchDog(struct adapter *Adapter)
+{
+ bool fw_current_in_ps_mode = false;
+ bool bFwPSAwake = true;
+ u8 hw_init_completed = false;
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+
+ hw_init_completed = Adapter->hw_init_completed;
+
+ if (hw_init_completed == false)
+ goto skip_dm;
+
+ fw_current_in_ps_mode = adapter_to_pwrctl(Adapter)->fw_current_in_ps_mode;
+ rtw_hal_get_hwreg(Adapter, HW_VAR_FWLPS_RF_ON, (u8 *)(&bFwPSAwake));
+
+ if (
+ (hw_init_completed == true) &&
+ ((!fw_current_in_ps_mode) && bFwPSAwake)
+ ) {
+ /* */
+ /* Calculate Tx/Rx statistics. */
+ /* */
+ dm_CheckStatistics(Adapter);
+ rtw_hal_check_rxfifo_full(Adapter);
+ }
+
+ /* ODM */
+ if (hw_init_completed == true) {
+ u8 bLinked = false;
+ u8 bsta_state = false;
+ bool bBtDisabled = true;
+
+ if (rtw_linked_check(Adapter)) {
+ bLinked = true;
+ if (check_fwstate(&Adapter->mlmepriv, WIFI_STATION_STATE))
+ bsta_state = true;
+ }
+
+ ODM_CmnInfoUpdate(&pHalData->odmpriv, ODM_CMNINFO_LINK, bLinked);
+ ODM_CmnInfoUpdate(&pHalData->odmpriv, ODM_CMNINFO_STATION_STATE, bsta_state);
+
+ /* ODM_CmnInfoUpdate(&pHalData->odmpriv , ODM_CMNINFO_RSSI_MIN, pdmpriv->MinUndecoratedPWDBForDM); */
+
+ bBtDisabled = hal_btcoex_IsBtDisabled(Adapter);
+
+ ODM_CmnInfoUpdate(&pHalData->odmpriv, ODM_CMNINFO_BT_ENABLED,
+ !bBtDisabled);
+
+ ODM_DMWatchdog(&pHalData->odmpriv);
+ }
+
+skip_dm:
+ return;
+}
+
+void rtl8723b_hal_dm_in_lps(struct adapter *padapter)
+{
+ u32 PWDB_rssi = 0;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct sta_info *psta = NULL;
+
+ /* update IGI */
+ ODM_Write_DIG(pDM_Odm, pDM_Odm->RSSI_Min);
+
+
+ /* set rssi to fw */
+ psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
+ if (psta && (psta->rssi_stat.UndecoratedSmoothedPWDB > 0)) {
+ PWDB_rssi = (psta->mac_id | (psta->rssi_stat.UndecoratedSmoothedPWDB<<16));
+
+ rtl8723b_set_rssi_cmd(padapter, (u8 *)&PWDB_rssi);
+ }
+
+}
+
+void rtl8723b_HalDmWatchDog_in_LPS(struct adapter *Adapter)
+{
+ u8 bLinked = false;
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+ struct mlme_priv *pmlmepriv = &Adapter->mlmepriv;
+ struct dm_priv *pdmpriv = &pHalData->dmpriv;
+ struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
+ struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
+ struct sta_priv *pstapriv = &Adapter->stapriv;
+ struct sta_info *psta = NULL;
+
+ if (Adapter->hw_init_completed == false)
+ goto skip_lps_dm;
+
+
+ if (rtw_linked_check(Adapter))
+ bLinked = true;
+
+ ODM_CmnInfoUpdate(&pHalData->odmpriv, ODM_CMNINFO_LINK, bLinked);
+
+ if (bLinked == false)
+ goto skip_lps_dm;
+
+ if (!(pDM_Odm->SupportAbility & ODM_BB_RSSI_MONITOR))
+ goto skip_lps_dm;
+
+
+ /* ODM_DMWatchdog(&pHalData->odmpriv); */
+ /* Do DIG by RSSI In LPS-32K */
+
+ /* 1 Find MIN-RSSI */
+ psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
+ if (!psta)
+ goto skip_lps_dm;
+
+ pdmpriv->EntryMinUndecoratedSmoothedPWDB = psta->rssi_stat.UndecoratedSmoothedPWDB;
+
+ if (pdmpriv->EntryMinUndecoratedSmoothedPWDB <= 0)
+ goto skip_lps_dm;
+
+ pdmpriv->MinUndecoratedPWDBForDM = pdmpriv->EntryMinUndecoratedSmoothedPWDB;
+
+ pDM_Odm->RSSI_Min = pdmpriv->MinUndecoratedPWDBForDM;
+
+ /* if (pDM_DigTable->CurIGValue != pDM_Odm->RSSI_Min) */
+ if (
+ (pDM_DigTable->CurIGValue > pDM_Odm->RSSI_Min + 5) ||
+ (pDM_DigTable->CurIGValue < pDM_Odm->RSSI_Min - 5)
+ )
+ rtw_dm_in_lps_wk_cmd(Adapter);
+
+
+skip_lps_dm:
+
+ return;
+
+}
+
+void rtl8723b_init_dm_priv(struct adapter *Adapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+ struct dm_priv *pdmpriv = &pHalData->dmpriv;
+
+ memset(pdmpriv, 0, sizeof(struct dm_priv));
+ Init_ODM_ComInfo_8723b(Adapter);
+}
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c b/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c
new file mode 100644
index 000000000..f1fc077ed
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c
@@ -0,0 +1,3863 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2013 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include <linux/firmware.h>
+#include <linux/slab.h>
+#include <drv_types.h>
+#include <rtw_debug.h>
+#include <rtl8723b_hal.h>
+#include "hal_com_h2c.h"
+
+static void _FWDownloadEnable(struct adapter *padapter, bool enable)
+{
+ u8 tmp, count = 0;
+
+ if (enable) {
+ /* 8051 enable */
+ tmp = rtw_read8(padapter, REG_SYS_FUNC_EN+1);
+ rtw_write8(padapter, REG_SYS_FUNC_EN+1, tmp|0x04);
+
+ tmp = rtw_read8(padapter, REG_MCUFWDL);
+ rtw_write8(padapter, REG_MCUFWDL, tmp|0x01);
+
+ do {
+ tmp = rtw_read8(padapter, REG_MCUFWDL);
+ if (tmp & 0x01)
+ break;
+ rtw_write8(padapter, REG_MCUFWDL, tmp|0x01);
+ msleep(1);
+ } while (count++ < 100);
+
+ /* 8051 reset */
+ tmp = rtw_read8(padapter, REG_MCUFWDL+2);
+ rtw_write8(padapter, REG_MCUFWDL+2, tmp&0xf7);
+ } else {
+ /* MCU firmware download disable. */
+ tmp = rtw_read8(padapter, REG_MCUFWDL);
+ rtw_write8(padapter, REG_MCUFWDL, tmp&0xfe);
+ }
+}
+
+static int _BlockWrite(struct adapter *padapter, void *buffer, u32 buffSize)
+{
+ int ret = _SUCCESS;
+
+ u32 blockSize_p1 = 4; /* (Default) Phase #1 : PCI muse use 4-byte write to download FW */
+ u32 blockSize_p2 = 8; /* Phase #2 : Use 8-byte, if Phase#1 use big size to write FW. */
+ u32 blockSize_p3 = 1; /* Phase #3 : Use 1-byte, the remnant of FW image. */
+ u32 blockCount_p1 = 0, blockCount_p2 = 0, blockCount_p3 = 0;
+ u32 remainSize_p1 = 0, remainSize_p2 = 0;
+ u8 *bufferPtr = buffer;
+ u32 i = 0, offset = 0;
+
+/* printk("====>%s %d\n", __func__, __LINE__); */
+
+ /* 3 Phase #1 */
+ blockCount_p1 = buffSize / blockSize_p1;
+ remainSize_p1 = buffSize % blockSize_p1;
+
+ for (i = 0; i < blockCount_p1; i++) {
+ ret = rtw_write32(padapter, (FW_8723B_START_ADDRESS + i * blockSize_p1), *((u32 *)(bufferPtr + i * blockSize_p1)));
+ if (ret == _FAIL) {
+ printk("====>%s %d i:%d\n", __func__, __LINE__, i);
+ goto exit;
+ }
+ }
+
+ /* 3 Phase #2 */
+ if (remainSize_p1) {
+ offset = blockCount_p1 * blockSize_p1;
+
+ blockCount_p2 = remainSize_p1/blockSize_p2;
+ remainSize_p2 = remainSize_p1%blockSize_p2;
+ }
+
+ /* 3 Phase #3 */
+ if (remainSize_p2) {
+ offset = (blockCount_p1 * blockSize_p1) + (blockCount_p2 * blockSize_p2);
+
+ blockCount_p3 = remainSize_p2 / blockSize_p3;
+
+ for (i = 0; i < blockCount_p3; i++) {
+ ret = rtw_write8(padapter, (FW_8723B_START_ADDRESS + offset + i), *(bufferPtr + offset + i));
+
+ if (ret == _FAIL) {
+ printk("====>%s %d i:%d\n", __func__, __LINE__, i);
+ goto exit;
+ }
+ }
+ }
+exit:
+ return ret;
+}
+
+static int _PageWrite(
+ struct adapter *padapter,
+ u32 page,
+ void *buffer,
+ u32 size
+)
+{
+ u8 value8;
+ u8 u8Page = (u8) (page & 0x07);
+
+ value8 = (rtw_read8(padapter, REG_MCUFWDL+2) & 0xF8) | u8Page;
+ rtw_write8(padapter, REG_MCUFWDL+2, value8);
+
+ return _BlockWrite(padapter, buffer, size);
+}
+
+static int _WriteFW(struct adapter *padapter, void *buffer, u32 size)
+{
+ /* Since we need dynamic decide method of dwonload fw, so we call this function to get chip version. */
+ /* We can remove _ReadChipVersion from ReadpadapterInfo8192C later. */
+ int ret = _SUCCESS;
+ u32 pageNums, remainSize;
+ u32 page, offset;
+ u8 *bufferPtr = buffer;
+
+ pageNums = size / MAX_DLFW_PAGE_SIZE;
+ remainSize = size % MAX_DLFW_PAGE_SIZE;
+
+ for (page = 0; page < pageNums; page++) {
+ offset = page * MAX_DLFW_PAGE_SIZE;
+ ret = _PageWrite(padapter, page, bufferPtr+offset, MAX_DLFW_PAGE_SIZE);
+
+ if (ret == _FAIL) {
+ printk("====>%s %d\n", __func__, __LINE__);
+ goto exit;
+ }
+ }
+
+ if (remainSize) {
+ offset = pageNums * MAX_DLFW_PAGE_SIZE;
+ page = pageNums;
+ ret = _PageWrite(padapter, page, bufferPtr+offset, remainSize);
+
+ if (ret == _FAIL) {
+ printk("====>%s %d\n", __func__, __LINE__);
+ goto exit;
+ }
+ }
+
+exit:
+ return ret;
+}
+
+void _8051Reset8723(struct adapter *padapter)
+{
+ u8 cpu_rst;
+ u8 io_rst;
+
+
+ /* Reset 8051(WLMCU) IO wrapper */
+ /* 0x1c[8] = 0 */
+ /* Suggested by Isaac@SD1 and Gimmy@SD1, coding by Lucas@20130624 */
+ io_rst = rtw_read8(padapter, REG_RSV_CTRL+1);
+ io_rst &= ~BIT(0);
+ rtw_write8(padapter, REG_RSV_CTRL+1, io_rst);
+
+ cpu_rst = rtw_read8(padapter, REG_SYS_FUNC_EN+1);
+ cpu_rst &= ~BIT(2);
+ rtw_write8(padapter, REG_SYS_FUNC_EN+1, cpu_rst);
+
+ /* Enable 8051 IO wrapper */
+ /* 0x1c[8] = 1 */
+ io_rst = rtw_read8(padapter, REG_RSV_CTRL+1);
+ io_rst |= BIT(0);
+ rtw_write8(padapter, REG_RSV_CTRL+1, io_rst);
+
+ cpu_rst = rtw_read8(padapter, REG_SYS_FUNC_EN+1);
+ cpu_rst |= BIT(2);
+ rtw_write8(padapter, REG_SYS_FUNC_EN+1, cpu_rst);
+}
+
+u8 g_fwdl_chksum_fail;
+
+static s32 polling_fwdl_chksum(
+ struct adapter *adapter, u32 min_cnt, u32 timeout_ms
+)
+{
+ s32 ret = _FAIL;
+ u32 value32;
+ unsigned long start = jiffies;
+ u32 cnt = 0;
+
+ /* polling CheckSum report */
+ do {
+ cnt++;
+ value32 = rtw_read32(adapter, REG_MCUFWDL);
+ if (value32 & FWDL_ChkSum_rpt || adapter->bSurpriseRemoved || adapter->bDriverStopped)
+ break;
+ yield();
+ } while (jiffies_to_msecs(jiffies-start) < timeout_ms || cnt < min_cnt);
+
+ if (!(value32 & FWDL_ChkSum_rpt)) {
+ goto exit;
+ }
+
+ if (g_fwdl_chksum_fail) {
+ g_fwdl_chksum_fail--;
+ goto exit;
+ }
+
+ ret = _SUCCESS;
+
+exit:
+
+ return ret;
+}
+
+u8 g_fwdl_wintint_rdy_fail;
+
+static s32 _FWFreeToGo(struct adapter *adapter, u32 min_cnt, u32 timeout_ms)
+{
+ s32 ret = _FAIL;
+ u32 value32;
+ unsigned long start = jiffies;
+ u32 cnt = 0;
+
+ value32 = rtw_read32(adapter, REG_MCUFWDL);
+ value32 |= MCUFWDL_RDY;
+ value32 &= ~WINTINI_RDY;
+ rtw_write32(adapter, REG_MCUFWDL, value32);
+
+ _8051Reset8723(adapter);
+
+ /* polling for FW ready */
+ do {
+ cnt++;
+ value32 = rtw_read32(adapter, REG_MCUFWDL);
+ if (value32 & WINTINI_RDY || adapter->bSurpriseRemoved || adapter->bDriverStopped)
+ break;
+ yield();
+ } while (jiffies_to_msecs(jiffies - start) < timeout_ms || cnt < min_cnt);
+
+ if (!(value32 & WINTINI_RDY)) {
+ goto exit;
+ }
+
+ if (g_fwdl_wintint_rdy_fail) {
+ g_fwdl_wintint_rdy_fail--;
+ goto exit;
+ }
+
+ ret = _SUCCESS;
+
+exit:
+
+ return ret;
+}
+
+#define IS_FW_81xxC(padapter) (((GET_HAL_DATA(padapter))->FirmwareSignature & 0xFFF0) == 0x88C0)
+
+void rtl8723b_FirmwareSelfReset(struct adapter *padapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ u8 u1bTmp;
+ u8 Delay = 100;
+
+ if (
+ !(IS_FW_81xxC(padapter) && ((pHalData->FirmwareVersion < 0x21) || (pHalData->FirmwareVersion == 0x21 && pHalData->FirmwareSubVersion < 0x01)))
+ ) { /* after 88C Fw v33.1 */
+ /* 0x1cf = 0x20. Inform 8051 to reset. 2009.12.25. tynli_test */
+ rtw_write8(padapter, REG_HMETFR+3, 0x20);
+
+ u1bTmp = rtw_read8(padapter, REG_SYS_FUNC_EN+1);
+ while (u1bTmp & BIT2) {
+ Delay--;
+ if (Delay == 0)
+ break;
+ udelay(50);
+ u1bTmp = rtw_read8(padapter, REG_SYS_FUNC_EN+1);
+ }
+
+ if (Delay == 0) {
+ /* force firmware reset */
+ u1bTmp = rtw_read8(padapter, REG_SYS_FUNC_EN+1);
+ rtw_write8(padapter, REG_SYS_FUNC_EN+1, u1bTmp&(~BIT2));
+ }
+ }
+}
+
+/* */
+/* Description: */
+/* Download 8192C firmware code. */
+/* */
+/* */
+s32 rtl8723b_FirmwareDownload(struct adapter *padapter, bool bUsedWoWLANFw)
+{
+ s32 rtStatus = _SUCCESS;
+ u8 write_fw = 0;
+ unsigned long fwdl_start_time;
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct rt_firmware *pFirmware;
+ struct rt_firmware *pBTFirmware;
+ struct rt_firmware_hdr *pFwHdr = NULL;
+ u8 *pFirmwareBuf;
+ u32 FirmwareLen;
+ const struct firmware *fw;
+ struct device *device = dvobj_to_dev(padapter->dvobj);
+ u8 *fwfilepath;
+ struct dvobj_priv *psdpriv = padapter->dvobj;
+ struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
+ u8 tmp_ps;
+
+ pFirmware = kzalloc(sizeof(struct rt_firmware), GFP_KERNEL);
+ if (!pFirmware)
+ return _FAIL;
+ pBTFirmware = kzalloc(sizeof(struct rt_firmware), GFP_KERNEL);
+ if (!pBTFirmware) {
+ kfree(pFirmware);
+ return _FAIL;
+ }
+ tmp_ps = rtw_read8(padapter, 0xa3);
+ tmp_ps &= 0xf8;
+ tmp_ps |= 0x02;
+ /* 1. write 0xA3[:2:0] = 3b'010 */
+ rtw_write8(padapter, 0xa3, tmp_ps);
+ /* 2. read power_state = 0xA0[1:0] */
+ tmp_ps = rtw_read8(padapter, 0xa0);
+ tmp_ps &= 0x03;
+ if (tmp_ps != 0x01)
+ pdbgpriv->dbg_downloadfw_pwr_state_cnt++;
+
+ fwfilepath = "rtlwifi/rtl8723bs_nic.bin";
+
+ pr_info("rtl8723bs: acquire FW from file:%s\n", fwfilepath);
+
+ rtStatus = request_firmware(&fw, fwfilepath, device);
+ if (rtStatus) {
+ pr_err("Request firmware failed with error 0x%x\n", rtStatus);
+ rtStatus = _FAIL;
+ goto exit;
+ }
+
+ if (!fw) {
+ pr_err("Firmware %s not available\n", fwfilepath);
+ rtStatus = _FAIL;
+ goto exit;
+ }
+
+ if (fw->size > FW_8723B_SIZE) {
+ rtStatus = _FAIL;
+ goto exit;
+ }
+
+ pFirmware->fw_buffer_sz = kmemdup(fw->data, fw->size, GFP_KERNEL);
+ if (!pFirmware->fw_buffer_sz) {
+ rtStatus = _FAIL;
+ goto exit;
+ }
+
+ pFirmware->fw_length = fw->size;
+ release_firmware(fw);
+ if (pFirmware->fw_length > FW_8723B_SIZE) {
+ rtStatus = _FAIL;
+ netdev_emerg(padapter->pnetdev,
+ "Firmware size:%u exceed %u\n",
+ pFirmware->fw_length, FW_8723B_SIZE);
+ goto release_fw1;
+ }
+
+ pFirmwareBuf = pFirmware->fw_buffer_sz;
+ FirmwareLen = pFirmware->fw_length;
+
+ /* To Check Fw header. Added by tynli. 2009.12.04. */
+ pFwHdr = (struct rt_firmware_hdr *)pFirmwareBuf;
+
+ pHalData->FirmwareVersion = le16_to_cpu(pFwHdr->version);
+ pHalData->FirmwareSubVersion = le16_to_cpu(pFwHdr->subversion);
+ pHalData->FirmwareSignature = le16_to_cpu(pFwHdr->signature);
+
+ if (IS_FW_HEADER_EXIST_8723B(pFwHdr)) {
+ /* Shift 32 bytes for FW header */
+ pFirmwareBuf = pFirmwareBuf + 32;
+ FirmwareLen = FirmwareLen - 32;
+ }
+
+ /* Suggested by Filen. If 8051 is running in RAM code, driver should inform Fw to reset by itself, */
+ /* or it will cause download Fw fail. 2010.02.01. by tynli. */
+ if (rtw_read8(padapter, REG_MCUFWDL) & RAM_DL_SEL) { /* 8051 RAM code */
+ rtw_write8(padapter, REG_MCUFWDL, 0x00);
+ rtl8723b_FirmwareSelfReset(padapter);
+ }
+
+ _FWDownloadEnable(padapter, true);
+ fwdl_start_time = jiffies;
+ while (
+ !padapter->bDriverStopped &&
+ !padapter->bSurpriseRemoved &&
+ (write_fw++ < 3 || jiffies_to_msecs(jiffies - fwdl_start_time) < 500)
+ ) {
+ /* reset FWDL chksum */
+ rtw_write8(padapter, REG_MCUFWDL, rtw_read8(padapter, REG_MCUFWDL)|FWDL_ChkSum_rpt);
+
+ rtStatus = _WriteFW(padapter, pFirmwareBuf, FirmwareLen);
+ if (rtStatus != _SUCCESS)
+ continue;
+
+ rtStatus = polling_fwdl_chksum(padapter, 5, 50);
+ if (rtStatus == _SUCCESS)
+ break;
+ }
+ _FWDownloadEnable(padapter, false);
+ if (_SUCCESS != rtStatus)
+ goto fwdl_stat;
+
+ rtStatus = _FWFreeToGo(padapter, 10, 200);
+ if (_SUCCESS != rtStatus)
+ goto fwdl_stat;
+
+fwdl_stat:
+
+exit:
+ kfree(pFirmware->fw_buffer_sz);
+ kfree(pFirmware);
+release_fw1:
+ kfree(pBTFirmware);
+ return rtStatus;
+}
+
+void rtl8723b_InitializeFirmwareVars(struct adapter *padapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+
+ /* Init Fw LPS related. */
+ adapter_to_pwrctl(padapter)->fw_current_in_ps_mode = false;
+
+ /* Init H2C cmd. */
+ rtw_write8(padapter, REG_HMETFR, 0x0f);
+
+ /* Init H2C counter. by tynli. 2009.12.09. */
+ pHalData->LastHMEBoxNum = 0;
+/* pHalData->H2CQueueHead = 0; */
+/* pHalData->H2CQueueTail = 0; */
+/* pHalData->H2CStopInsertQueue = false; */
+}
+
+static void rtl8723b_free_hal_data(struct adapter *padapter)
+{
+}
+
+/* */
+/* Efuse related code */
+/* */
+static u8 hal_EfuseSwitchToBank(
+ struct adapter *padapter, u8 bank, bool bPseudoTest
+)
+{
+ u8 bRet = false;
+ u32 value32 = 0;
+#ifdef HAL_EFUSE_MEMORY
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct efuse_hal *pEfuseHal = &pHalData->EfuseHal;
+#endif
+
+
+ if (bPseudoTest) {
+#ifdef HAL_EFUSE_MEMORY
+ pEfuseHal->fakeEfuseBank = bank;
+#else
+ fakeEfuseBank = bank;
+#endif
+ bRet = true;
+ } else {
+ value32 = rtw_read32(padapter, EFUSE_TEST);
+ bRet = true;
+ switch (bank) {
+ case 0:
+ value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_WIFI_SEL_0);
+ break;
+ case 1:
+ value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_BT_SEL_0);
+ break;
+ case 2:
+ value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_BT_SEL_1);
+ break;
+ case 3:
+ value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_BT_SEL_2);
+ break;
+ default:
+ value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_WIFI_SEL_0);
+ bRet = false;
+ break;
+ }
+ rtw_write32(padapter, EFUSE_TEST, value32);
+ }
+
+ return bRet;
+}
+
+static void Hal_GetEfuseDefinition(
+ struct adapter *padapter,
+ u8 efuseType,
+ u8 type,
+ void *pOut,
+ bool bPseudoTest
+)
+{
+ switch (type) {
+ case TYPE_EFUSE_MAX_SECTION:
+ {
+ u8 *pMax_section;
+ pMax_section = pOut;
+
+ if (efuseType == EFUSE_WIFI)
+ *pMax_section = EFUSE_MAX_SECTION_8723B;
+ else
+ *pMax_section = EFUSE_BT_MAX_SECTION;
+ }
+ break;
+
+ case TYPE_EFUSE_REAL_CONTENT_LEN:
+ {
+ u16 *pu2Tmp;
+ pu2Tmp = pOut;
+
+ if (efuseType == EFUSE_WIFI)
+ *pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723B;
+ else
+ *pu2Tmp = EFUSE_BT_REAL_CONTENT_LEN;
+ }
+ break;
+
+ case TYPE_AVAILABLE_EFUSE_BYTES_BANK:
+ {
+ u16 *pu2Tmp;
+ pu2Tmp = pOut;
+
+ if (efuseType == EFUSE_WIFI)
+ *pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723B-EFUSE_OOB_PROTECT_BYTES);
+ else
+ *pu2Tmp = (EFUSE_BT_REAL_BANK_CONTENT_LEN-EFUSE_PROTECT_BYTES_BANK);
+ }
+ break;
+
+ case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL:
+ {
+ u16 *pu2Tmp;
+ pu2Tmp = pOut;
+
+ if (efuseType == EFUSE_WIFI)
+ *pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723B-EFUSE_OOB_PROTECT_BYTES);
+ else
+ *pu2Tmp = (EFUSE_BT_REAL_CONTENT_LEN-(EFUSE_PROTECT_BYTES_BANK*3));
+ }
+ break;
+
+ case TYPE_EFUSE_MAP_LEN:
+ {
+ u16 *pu2Tmp;
+ pu2Tmp = pOut;
+
+ if (efuseType == EFUSE_WIFI)
+ *pu2Tmp = EFUSE_MAX_MAP_LEN;
+ else
+ *pu2Tmp = EFUSE_BT_MAP_LEN;
+ }
+ break;
+
+ case TYPE_EFUSE_PROTECT_BYTES_BANK:
+ {
+ u8 *pu1Tmp;
+ pu1Tmp = pOut;
+
+ if (efuseType == EFUSE_WIFI)
+ *pu1Tmp = EFUSE_OOB_PROTECT_BYTES;
+ else
+ *pu1Tmp = EFUSE_PROTECT_BYTES_BANK;
+ }
+ break;
+
+ case TYPE_EFUSE_CONTENT_LEN_BANK:
+ {
+ u16 *pu2Tmp;
+ pu2Tmp = pOut;
+
+ if (efuseType == EFUSE_WIFI)
+ *pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723B;
+ else
+ *pu2Tmp = EFUSE_BT_REAL_BANK_CONTENT_LEN;
+ }
+ break;
+
+ default:
+ {
+ u8 *pu1Tmp;
+ pu1Tmp = pOut;
+ *pu1Tmp = 0;
+ }
+ break;
+ }
+}
+
+#define VOLTAGE_V25 0x03
+
+/* */
+/* The following is for compile ok */
+/* That should be merged with the original in the future */
+/* */
+#define EFUSE_ACCESS_ON_8723 0x69 /* For RTL8723 only. */
+#define REG_EFUSE_ACCESS_8723 0x00CF /* Efuse access protection for RTL8723 */
+
+/* */
+static void Hal_BT_EfusePowerSwitch(
+ struct adapter *padapter, u8 bWrite, u8 PwrState
+)
+{
+ u8 tempval;
+ if (PwrState) {
+ /* enable BT power cut */
+ /* 0x6A[14] = 1 */
+ tempval = rtw_read8(padapter, 0x6B);
+ tempval |= BIT(6);
+ rtw_write8(padapter, 0x6B, tempval);
+
+ /* Attention!! Between 0x6A[14] and 0x6A[15] setting need 100us delay */
+ /* So don't write 0x6A[14]= 1 and 0x6A[15]= 0 together! */
+ msleep(1);
+ /* disable BT output isolation */
+ /* 0x6A[15] = 0 */
+ tempval = rtw_read8(padapter, 0x6B);
+ tempval &= ~BIT(7);
+ rtw_write8(padapter, 0x6B, tempval);
+ } else {
+ /* enable BT output isolation */
+ /* 0x6A[15] = 1 */
+ tempval = rtw_read8(padapter, 0x6B);
+ tempval |= BIT(7);
+ rtw_write8(padapter, 0x6B, tempval);
+
+ /* Attention!! Between 0x6A[14] and 0x6A[15] setting need 100us delay */
+ /* So don't write 0x6A[14]= 1 and 0x6A[15]= 0 together! */
+
+ /* disable BT power cut */
+ /* 0x6A[14] = 1 */
+ tempval = rtw_read8(padapter, 0x6B);
+ tempval &= ~BIT(6);
+ rtw_write8(padapter, 0x6B, tempval);
+ }
+
+}
+static void Hal_EfusePowerSwitch(
+ struct adapter *padapter, u8 bWrite, u8 PwrState
+)
+{
+ u8 tempval;
+ u16 tmpV16;
+
+
+ if (PwrState) {
+ /* To avoid cannot access efuse regsiters after disable/enable several times during DTM test. */
+ /* Suggested by SD1 IsaacHsu. 2013.07.08, added by tynli. */
+ tempval = rtw_read8(padapter, SDIO_LOCAL_BASE|SDIO_REG_HSUS_CTRL);
+ if (tempval & BIT(0)) { /* SDIO local register is suspend */
+ u8 count = 0;
+
+
+ tempval &= ~BIT(0);
+ rtw_write8(padapter, SDIO_LOCAL_BASE|SDIO_REG_HSUS_CTRL, tempval);
+
+ /* check 0x86[1:0]= 10'2h, wait power state to leave suspend */
+ do {
+ tempval = rtw_read8(padapter, SDIO_LOCAL_BASE|SDIO_REG_HSUS_CTRL);
+ tempval &= 0x3;
+ if (tempval == 0x02)
+ break;
+
+ count++;
+ if (count >= 100)
+ break;
+
+ mdelay(10);
+ } while (1);
+ }
+
+ rtw_write8(padapter, REG_EFUSE_ACCESS_8723, EFUSE_ACCESS_ON_8723);
+
+ /* Reset: 0x0000h[28], default valid */
+ tmpV16 = rtw_read16(padapter, REG_SYS_FUNC_EN);
+ if (!(tmpV16 & FEN_ELDR)) {
+ tmpV16 |= FEN_ELDR;
+ rtw_write16(padapter, REG_SYS_FUNC_EN, tmpV16);
+ }
+
+ /* Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid */
+ tmpV16 = rtw_read16(padapter, REG_SYS_CLKR);
+ if ((!(tmpV16 & LOADER_CLK_EN)) || (!(tmpV16 & ANA8M))) {
+ tmpV16 |= (LOADER_CLK_EN | ANA8M);
+ rtw_write16(padapter, REG_SYS_CLKR, tmpV16);
+ }
+
+ if (bWrite) {
+ /* Enable LDO 2.5V before read/write action */
+ tempval = rtw_read8(padapter, EFUSE_TEST+3);
+ tempval &= 0x0F;
+ tempval |= (VOLTAGE_V25 << 4);
+ rtw_write8(padapter, EFUSE_TEST+3, (tempval | 0x80));
+
+ /* rtw_write8(padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON); */
+ }
+ } else {
+ rtw_write8(padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);
+
+ if (bWrite) {
+ /* Disable LDO 2.5V after read/write action */
+ tempval = rtw_read8(padapter, EFUSE_TEST+3);
+ rtw_write8(padapter, EFUSE_TEST+3, (tempval & 0x7F));
+ }
+
+ }
+}
+
+static void hal_ReadEFuse_WiFi(
+ struct adapter *padapter,
+ u16 _offset,
+ u16 _size_byte,
+ u8 *pbuf,
+ bool bPseudoTest
+)
+{
+#ifdef HAL_EFUSE_MEMORY
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct efuse_hal *pEfuseHal = &pHalData->EfuseHal;
+#endif
+ u8 *efuseTbl = NULL;
+ u16 eFuse_Addr = 0;
+ u8 offset, wden;
+ u8 efuseHeader, efuseExtHdr, efuseData;
+ u16 i, total, used;
+ u8 efuse_usage = 0;
+
+ /* */
+ /* Do NOT excess total size of EFuse table. Added by Roger, 2008.11.10. */
+ /* */
+ if ((_offset + _size_byte) > EFUSE_MAX_MAP_LEN)
+ return;
+
+ efuseTbl = rtw_malloc(EFUSE_MAX_MAP_LEN);
+ if (!efuseTbl)
+ return;
+
+ /* 0xff will be efuse default value instead of 0x00. */
+ memset(efuseTbl, 0xFF, EFUSE_MAX_MAP_LEN);
+
+ /* switch bank back to bank 0 for later BT and wifi use. */
+ hal_EfuseSwitchToBank(padapter, 0, bPseudoTest);
+
+ while (AVAILABLE_EFUSE_ADDR(eFuse_Addr)) {
+ efuse_OneByteRead(padapter, eFuse_Addr++, &efuseHeader, bPseudoTest);
+ if (efuseHeader == 0xFF)
+ break;
+
+ /* Check PG header for section num. */
+ if (EXT_HEADER(efuseHeader)) { /* extended header */
+ offset = GET_HDR_OFFSET_2_0(efuseHeader);
+
+ efuse_OneByteRead(padapter, eFuse_Addr++, &efuseExtHdr, bPseudoTest);
+ if (ALL_WORDS_DISABLED(efuseExtHdr))
+ continue;
+
+ offset |= ((efuseExtHdr & 0xF0) >> 1);
+ wden = (efuseExtHdr & 0x0F);
+ } else {
+ offset = ((efuseHeader >> 4) & 0x0f);
+ wden = (efuseHeader & 0x0f);
+ }
+
+ if (offset < EFUSE_MAX_SECTION_8723B) {
+ u16 addr;
+ /* Get word enable value from PG header */
+
+ addr = offset * PGPKT_DATA_SIZE;
+ for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
+ /* Check word enable condition in the section */
+ if (!(wden & (0x01<<i))) {
+ efuse_OneByteRead(padapter, eFuse_Addr++, &efuseData, bPseudoTest);
+ efuseTbl[addr] = efuseData;
+
+ efuse_OneByteRead(padapter, eFuse_Addr++, &efuseData, bPseudoTest);
+ efuseTbl[addr+1] = efuseData;
+ }
+ addr += 2;
+ }
+ } else {
+ eFuse_Addr += Efuse_CalculateWordCnts(wden)*2;
+ }
+ }
+
+ /* Copy from Efuse map to output pointer memory!!! */
+ for (i = 0; i < _size_byte; i++)
+ pbuf[i] = efuseTbl[_offset+i];
+
+ /* Calculate Efuse utilization */
+ EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &total, bPseudoTest);
+ used = eFuse_Addr - 1;
+ efuse_usage = (u8)((used*100)/total);
+ if (bPseudoTest) {
+#ifdef HAL_EFUSE_MEMORY
+ pEfuseHal->fakeEfuseUsedBytes = used;
+#else
+ fakeEfuseUsedBytes = used;
+#endif
+ } else {
+ rtw_hal_set_hwreg(padapter, HW_VAR_EFUSE_BYTES, (u8 *)&used);
+ rtw_hal_set_hwreg(padapter, HW_VAR_EFUSE_USAGE, (u8 *)&efuse_usage);
+ }
+
+ kfree(efuseTbl);
+}
+
+static void hal_ReadEFuse_BT(
+ struct adapter *padapter,
+ u16 _offset,
+ u16 _size_byte,
+ u8 *pbuf,
+ bool bPseudoTest
+)
+{
+#ifdef HAL_EFUSE_MEMORY
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct efuse_hal *pEfuseHal = &pHalData->EfuseHal;
+#endif
+ u8 *efuseTbl;
+ u8 bank;
+ u16 eFuse_Addr;
+ u8 efuseHeader, efuseExtHdr, efuseData;
+ u8 offset, wden;
+ u16 i, total, used;
+ u8 efuse_usage;
+
+
+ /* */
+ /* Do NOT excess total size of EFuse table. Added by Roger, 2008.11.10. */
+ /* */
+ if ((_offset + _size_byte) > EFUSE_BT_MAP_LEN)
+ return;
+
+ efuseTbl = rtw_malloc(EFUSE_BT_MAP_LEN);
+ if (!efuseTbl)
+ return;
+
+ /* 0xff will be efuse default value instead of 0x00. */
+ memset(efuseTbl, 0xFF, EFUSE_BT_MAP_LEN);
+
+ EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_BANK, &total, bPseudoTest);
+
+ for (bank = 1; bank < 3; bank++) { /* 8723b Max bake 0~2 */
+ if (hal_EfuseSwitchToBank(padapter, bank, bPseudoTest) == false)
+ goto exit;
+
+ eFuse_Addr = 0;
+
+ while (AVAILABLE_EFUSE_ADDR(eFuse_Addr)) {
+ efuse_OneByteRead(padapter, eFuse_Addr++, &efuseHeader, bPseudoTest);
+ if (efuseHeader == 0xFF)
+ break;
+
+ /* Check PG header for section num. */
+ if (EXT_HEADER(efuseHeader)) { /* extended header */
+ offset = GET_HDR_OFFSET_2_0(efuseHeader);
+
+ efuse_OneByteRead(padapter, eFuse_Addr++, &efuseExtHdr, bPseudoTest);
+ if (ALL_WORDS_DISABLED(efuseExtHdr))
+ continue;
+
+
+ offset |= ((efuseExtHdr & 0xF0) >> 1);
+ wden = (efuseExtHdr & 0x0F);
+ } else {
+ offset = ((efuseHeader >> 4) & 0x0f);
+ wden = (efuseHeader & 0x0f);
+ }
+
+ if (offset < EFUSE_BT_MAX_SECTION) {
+ u16 addr;
+
+ addr = offset * PGPKT_DATA_SIZE;
+ for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
+ /* Check word enable condition in the section */
+ if (!(wden & (0x01<<i))) {
+ efuse_OneByteRead(padapter, eFuse_Addr++, &efuseData, bPseudoTest);
+ efuseTbl[addr] = efuseData;
+
+ efuse_OneByteRead(padapter, eFuse_Addr++, &efuseData, bPseudoTest);
+ efuseTbl[addr+1] = efuseData;
+ }
+ addr += 2;
+ }
+ } else {
+ eFuse_Addr += Efuse_CalculateWordCnts(wden)*2;
+ }
+ }
+
+ if ((eFuse_Addr - 1) < total)
+ break;
+
+ }
+
+ /* switch bank back to bank 0 for later BT and wifi use. */
+ hal_EfuseSwitchToBank(padapter, 0, bPseudoTest);
+
+ /* Copy from Efuse map to output pointer memory!!! */
+ for (i = 0; i < _size_byte; i++)
+ pbuf[i] = efuseTbl[_offset+i];
+
+ /* */
+ /* Calculate Efuse utilization. */
+ /* */
+ EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &total, bPseudoTest);
+ used = (EFUSE_BT_REAL_BANK_CONTENT_LEN*(bank-1)) + eFuse_Addr - 1;
+ efuse_usage = (u8)((used*100)/total);
+ if (bPseudoTest) {
+#ifdef HAL_EFUSE_MEMORY
+ pEfuseHal->fakeBTEfuseUsedBytes = used;
+#else
+ fakeBTEfuseUsedBytes = used;
+#endif
+ } else {
+ rtw_hal_set_hwreg(padapter, HW_VAR_EFUSE_BT_BYTES, (u8 *)&used);
+ rtw_hal_set_hwreg(padapter, HW_VAR_EFUSE_BT_USAGE, (u8 *)&efuse_usage);
+ }
+
+exit:
+ kfree(efuseTbl);
+}
+
+static void Hal_ReadEFuse(
+ struct adapter *padapter,
+ u8 efuseType,
+ u16 _offset,
+ u16 _size_byte,
+ u8 *pbuf,
+ bool bPseudoTest
+)
+{
+ if (efuseType == EFUSE_WIFI)
+ hal_ReadEFuse_WiFi(padapter, _offset, _size_byte, pbuf, bPseudoTest);
+ else
+ hal_ReadEFuse_BT(padapter, _offset, _size_byte, pbuf, bPseudoTest);
+}
+
+static u16 hal_EfuseGetCurrentSize_WiFi(
+ struct adapter *padapter, bool bPseudoTest
+)
+{
+#ifdef HAL_EFUSE_MEMORY
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct efuse_hal *pEfuseHal = &pHalData->EfuseHal;
+#endif
+ u16 efuse_addr = 0;
+ u16 start_addr = 0; /* for debug */
+ u8 hoffset = 0, hworden = 0;
+ u8 efuse_data, word_cnts = 0;
+ u32 count = 0; /* for debug */
+
+
+ if (bPseudoTest) {
+#ifdef HAL_EFUSE_MEMORY
+ efuse_addr = (u16)pEfuseHal->fakeEfuseUsedBytes;
+#else
+ efuse_addr = (u16)fakeEfuseUsedBytes;
+#endif
+ } else
+ rtw_hal_get_hwreg(padapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr);
+
+ start_addr = efuse_addr;
+
+ /* switch bank back to bank 0 for later BT and wifi use. */
+ hal_EfuseSwitchToBank(padapter, 0, bPseudoTest);
+
+ count = 0;
+ while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
+ if (efuse_OneByteRead(padapter, efuse_addr, &efuse_data, bPseudoTest) == false)
+ goto error;
+
+ if (efuse_data == 0xFF)
+ break;
+
+ if ((start_addr != 0) && (efuse_addr == start_addr)) {
+ count++;
+
+ efuse_data = 0xFF;
+ if (count < 4) {
+ /* try again! */
+
+ if (count > 2) {
+ /* try again form address 0 */
+ efuse_addr = 0;
+ start_addr = 0;
+ }
+
+ continue;
+ }
+
+ goto error;
+ }
+
+ if (EXT_HEADER(efuse_data)) {
+ hoffset = GET_HDR_OFFSET_2_0(efuse_data);
+ efuse_addr++;
+ efuse_OneByteRead(padapter, efuse_addr, &efuse_data, bPseudoTest);
+ if (ALL_WORDS_DISABLED(efuse_data))
+ continue;
+
+ hoffset |= ((efuse_data & 0xF0) >> 1);
+ hworden = efuse_data & 0x0F;
+ } else {
+ hoffset = (efuse_data>>4) & 0x0F;
+ hworden = efuse_data & 0x0F;
+ }
+
+ word_cnts = Efuse_CalculateWordCnts(hworden);
+ efuse_addr += (word_cnts*2)+1;
+ }
+
+ if (bPseudoTest) {
+#ifdef HAL_EFUSE_MEMORY
+ pEfuseHal->fakeEfuseUsedBytes = efuse_addr;
+#else
+ fakeEfuseUsedBytes = efuse_addr;
+#endif
+ } else
+ rtw_hal_set_hwreg(padapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr);
+
+ goto exit;
+
+error:
+ /* report max size to prevent write efuse */
+ EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &efuse_addr, bPseudoTest);
+
+exit:
+
+ return efuse_addr;
+}
+
+static u16 hal_EfuseGetCurrentSize_BT(struct adapter *padapter, u8 bPseudoTest)
+{
+#ifdef HAL_EFUSE_MEMORY
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct efuse_hal *pEfuseHal = &pHalData->EfuseHal;
+#endif
+ u16 btusedbytes;
+ u16 efuse_addr;
+ u8 bank, startBank;
+ u8 hoffset = 0, hworden = 0;
+ u8 efuse_data, word_cnts = 0;
+ u16 retU2 = 0;
+
+ if (bPseudoTest) {
+#ifdef HAL_EFUSE_MEMORY
+ btusedbytes = pEfuseHal->fakeBTEfuseUsedBytes;
+#else
+ btusedbytes = fakeBTEfuseUsedBytes;
+#endif
+ } else
+ rtw_hal_get_hwreg(padapter, HW_VAR_EFUSE_BT_BYTES, (u8 *)&btusedbytes);
+
+ efuse_addr = (u16)((btusedbytes%EFUSE_BT_REAL_BANK_CONTENT_LEN));
+ startBank = (u8)(1+(btusedbytes/EFUSE_BT_REAL_BANK_CONTENT_LEN));
+
+ EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_BANK, &retU2, bPseudoTest);
+
+ for (bank = startBank; bank < 3; bank++) {
+ if (hal_EfuseSwitchToBank(padapter, bank, bPseudoTest) == false)
+ /* bank = EFUSE_MAX_BANK; */
+ break;
+
+ /* only when bank is switched we have to reset the efuse_addr. */
+ if (bank != startBank)
+ efuse_addr = 0;
+#if 1
+
+ while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
+ if (efuse_OneByteRead(padapter, efuse_addr,
+ &efuse_data, bPseudoTest) == false)
+ /* bank = EFUSE_MAX_BANK; */
+ break;
+
+ if (efuse_data == 0xFF)
+ break;
+
+ if (EXT_HEADER(efuse_data)) {
+ hoffset = GET_HDR_OFFSET_2_0(efuse_data);
+ efuse_addr++;
+ efuse_OneByteRead(padapter, efuse_addr, &efuse_data, bPseudoTest);
+
+ if (ALL_WORDS_DISABLED(efuse_data)) {
+ efuse_addr++;
+ continue;
+ }
+
+/* hoffset = ((hoffset & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1); */
+ hoffset |= ((efuse_data & 0xF0) >> 1);
+ hworden = efuse_data & 0x0F;
+ } else {
+ hoffset = (efuse_data>>4) & 0x0F;
+ hworden = efuse_data & 0x0F;
+ }
+
+ word_cnts = Efuse_CalculateWordCnts(hworden);
+ /* read next header */
+ efuse_addr += (word_cnts*2)+1;
+ }
+#else
+ while (
+ bContinual &&
+ efuse_OneByteRead(padapter, efuse_addr, &efuse_data, bPseudoTest) &&
+ AVAILABLE_EFUSE_ADDR(efuse_addr)
+ ) {
+ if (efuse_data != 0xFF) {
+ if ((efuse_data&0x1F) == 0x0F) { /* extended header */
+ hoffset = efuse_data;
+ efuse_addr++;
+ efuse_OneByteRead(padapter, efuse_addr, &efuse_data, bPseudoTest);
+ if ((efuse_data & 0x0F) == 0x0F) {
+ efuse_addr++;
+ continue;
+ } else {
+ hoffset = ((hoffset & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
+ hworden = efuse_data & 0x0F;
+ }
+ } else {
+ hoffset = (efuse_data>>4) & 0x0F;
+ hworden = efuse_data & 0x0F;
+ }
+ word_cnts = Efuse_CalculateWordCnts(hworden);
+ /* read next header */
+ efuse_addr = efuse_addr + (word_cnts*2)+1;
+ } else
+ bContinual = false;
+ }
+#endif
+
+
+ /* Check if we need to check next bank efuse */
+ if (efuse_addr < retU2)
+ break; /* don't need to check next bank. */
+ }
+
+ retU2 = ((bank-1)*EFUSE_BT_REAL_BANK_CONTENT_LEN)+efuse_addr;
+ if (bPseudoTest) {
+ pEfuseHal->fakeBTEfuseUsedBytes = retU2;
+ } else {
+ pEfuseHal->BTEfuseUsedBytes = retU2;
+ }
+
+ return retU2;
+}
+
+static u16 Hal_EfuseGetCurrentSize(
+ struct adapter *padapter, u8 efuseType, bool bPseudoTest
+)
+{
+ u16 ret = 0;
+
+ if (efuseType == EFUSE_WIFI)
+ ret = hal_EfuseGetCurrentSize_WiFi(padapter, bPseudoTest);
+ else
+ ret = hal_EfuseGetCurrentSize_BT(padapter, bPseudoTest);
+
+ return ret;
+}
+
+static u8 Hal_EfuseWordEnableDataWrite(
+ struct adapter *padapter,
+ u16 efuse_addr,
+ u8 word_en,
+ u8 *data,
+ bool bPseudoTest
+)
+{
+ u16 tmpaddr = 0;
+ u16 start_addr = efuse_addr;
+ u8 badworden = 0x0F;
+ u8 tmpdata[PGPKT_DATA_SIZE];
+
+ memset(tmpdata, 0xFF, PGPKT_DATA_SIZE);
+
+ if (!(word_en & BIT(0))) {
+ tmpaddr = start_addr;
+ efuse_OneByteWrite(padapter, start_addr++, data[0], bPseudoTest);
+ efuse_OneByteWrite(padapter, start_addr++, data[1], bPseudoTest);
+
+ efuse_OneByteRead(padapter, tmpaddr, &tmpdata[0], bPseudoTest);
+ efuse_OneByteRead(padapter, tmpaddr+1, &tmpdata[1], bPseudoTest);
+ if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1])) {
+ badworden &= (~BIT(0));
+ }
+ }
+ if (!(word_en & BIT(1))) {
+ tmpaddr = start_addr;
+ efuse_OneByteWrite(padapter, start_addr++, data[2], bPseudoTest);
+ efuse_OneByteWrite(padapter, start_addr++, data[3], bPseudoTest);
+
+ efuse_OneByteRead(padapter, tmpaddr, &tmpdata[2], bPseudoTest);
+ efuse_OneByteRead(padapter, tmpaddr+1, &tmpdata[3], bPseudoTest);
+ if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3])) {
+ badworden &= (~BIT(1));
+ }
+ }
+
+ if (!(word_en & BIT(2))) {
+ tmpaddr = start_addr;
+ efuse_OneByteWrite(padapter, start_addr++, data[4], bPseudoTest);
+ efuse_OneByteWrite(padapter, start_addr++, data[5], bPseudoTest);
+
+ efuse_OneByteRead(padapter, tmpaddr, &tmpdata[4], bPseudoTest);
+ efuse_OneByteRead(padapter, tmpaddr+1, &tmpdata[5], bPseudoTest);
+ if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5])) {
+ badworden &= (~BIT(2));
+ }
+ }
+
+ if (!(word_en & BIT(3))) {
+ tmpaddr = start_addr;
+ efuse_OneByteWrite(padapter, start_addr++, data[6], bPseudoTest);
+ efuse_OneByteWrite(padapter, start_addr++, data[7], bPseudoTest);
+
+ efuse_OneByteRead(padapter, tmpaddr, &tmpdata[6], bPseudoTest);
+ efuse_OneByteRead(padapter, tmpaddr+1, &tmpdata[7], bPseudoTest);
+ if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7])) {
+ badworden &= (~BIT(3));
+ }
+ }
+
+ return badworden;
+}
+
+static s32 Hal_EfusePgPacketRead(
+ struct adapter *padapter,
+ u8 offset,
+ u8 *data,
+ bool bPseudoTest
+)
+{
+ u8 efuse_data, word_cnts = 0;
+ u16 efuse_addr = 0;
+ u8 hoffset = 0, hworden = 0;
+ u8 i;
+ u8 max_section = 0;
+ s32 ret;
+
+
+ if (!data)
+ return false;
+
+ EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAX_SECTION, &max_section, bPseudoTest);
+ if (offset > max_section)
+ return false;
+
+ memset(data, 0xFF, PGPKT_DATA_SIZE);
+ ret = true;
+
+ /* */
+ /* <Roger_TODO> Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. */
+ /* Skip dummy parts to prevent unexpected data read from Efuse. */
+ /* By pass right now. 2009.02.19. */
+ /* */
+ while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
+ if (efuse_OneByteRead(padapter, efuse_addr++, &efuse_data, bPseudoTest) == false) {
+ ret = false;
+ break;
+ }
+
+ if (efuse_data == 0xFF)
+ break;
+
+ if (EXT_HEADER(efuse_data)) {
+ hoffset = GET_HDR_OFFSET_2_0(efuse_data);
+ efuse_OneByteRead(padapter, efuse_addr++, &efuse_data, bPseudoTest);
+ if (ALL_WORDS_DISABLED(efuse_data))
+ continue;
+
+ hoffset |= ((efuse_data & 0xF0) >> 1);
+ hworden = efuse_data & 0x0F;
+ } else {
+ hoffset = (efuse_data>>4) & 0x0F;
+ hworden = efuse_data & 0x0F;
+ }
+
+ if (hoffset == offset) {
+ for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
+ /* Check word enable condition in the section */
+ if (!(hworden & (0x01<<i))) {
+ efuse_OneByteRead(padapter, efuse_addr++, &efuse_data, bPseudoTest);
+ data[i*2] = efuse_data;
+
+ efuse_OneByteRead(padapter, efuse_addr++, &efuse_data, bPseudoTest);
+ data[(i*2)+1] = efuse_data;
+ }
+ }
+ } else {
+ word_cnts = Efuse_CalculateWordCnts(hworden);
+ efuse_addr += word_cnts*2;
+ }
+ }
+
+ return ret;
+}
+
+static u8 hal_EfusePgCheckAvailableAddr(
+ struct adapter *padapter, u8 efuseType, u8 bPseudoTest
+)
+{
+ u16 max_available = 0;
+ u16 current_size;
+
+
+ EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &max_available, bPseudoTest);
+
+ current_size = Efuse_GetCurrentSize(padapter, efuseType, bPseudoTest);
+ if (current_size >= max_available)
+ return false;
+
+ return true;
+}
+
+static void hal_EfuseConstructPGPkt(
+ u8 offset,
+ u8 word_en,
+ u8 *pData,
+ struct pgpkt_struct *pTargetPkt
+)
+{
+ memset(pTargetPkt->data, 0xFF, PGPKT_DATA_SIZE);
+ pTargetPkt->offset = offset;
+ pTargetPkt->word_en = word_en;
+ efuse_WordEnableDataRead(word_en, pData, pTargetPkt->data);
+ pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
+}
+
+static u8 hal_EfusePartialWriteCheck(
+ struct adapter *padapter,
+ u8 efuseType,
+ u16 *pAddr,
+ struct pgpkt_struct *pTargetPkt,
+ u8 bPseudoTest
+)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct efuse_hal *pEfuseHal = &pHalData->EfuseHal;
+ u8 bRet = false;
+ u16 startAddr = 0, efuse_max_available_len = 0, efuse_max = 0;
+ u8 efuse_data = 0;
+
+ EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &efuse_max_available_len, bPseudoTest);
+ EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_EFUSE_CONTENT_LEN_BANK, &efuse_max, bPseudoTest);
+
+ if (efuseType == EFUSE_WIFI) {
+ if (bPseudoTest) {
+#ifdef HAL_EFUSE_MEMORY
+ startAddr = (u16)pEfuseHal->fakeEfuseUsedBytes;
+#else
+ startAddr = (u16)fakeEfuseUsedBytes;
+#endif
+ } else
+ rtw_hal_get_hwreg(padapter, HW_VAR_EFUSE_BYTES, (u8 *)&startAddr);
+ } else {
+ if (bPseudoTest) {
+#ifdef HAL_EFUSE_MEMORY
+ startAddr = (u16)pEfuseHal->fakeBTEfuseUsedBytes;
+#else
+ startAddr = (u16)fakeBTEfuseUsedBytes;
+#endif
+ } else
+ rtw_hal_get_hwreg(padapter, HW_VAR_EFUSE_BT_BYTES, (u8 *)&startAddr);
+ }
+ startAddr %= efuse_max;
+
+ while (1) {
+ if (startAddr >= efuse_max_available_len) {
+ bRet = false;
+ break;
+ }
+
+ if (efuse_OneByteRead(padapter, startAddr, &efuse_data, bPseudoTest) && (efuse_data != 0xFF)) {
+#if 1
+ bRet = false;
+ break;
+#else
+ if (EXT_HEADER(efuse_data)) {
+ cur_header = efuse_data;
+ startAddr++;
+ efuse_OneByteRead(padapter, startAddr, &efuse_data, bPseudoTest);
+ if (ALL_WORDS_DISABLED(efuse_data)) {
+ bRet = false;
+ break;
+ } else {
+ curPkt.offset = ((cur_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
+ curPkt.word_en = efuse_data & 0x0F;
+ }
+ } else {
+ cur_header = efuse_data;
+ curPkt.offset = (cur_header>>4) & 0x0F;
+ curPkt.word_en = cur_header & 0x0F;
+ }
+
+ curPkt.word_cnts = Efuse_CalculateWordCnts(curPkt.word_en);
+ /* if same header is found but no data followed */
+ /* write some part of data followed by the header. */
+ if (
+ (curPkt.offset == pTargetPkt->offset) &&
+ (hal_EfuseCheckIfDatafollowed(padapter, curPkt.word_cnts, startAddr+1, bPseudoTest) == false) &&
+ wordEnMatched(pTargetPkt, &curPkt, &matched_wden) == true
+ ) {
+ /* Here to write partial data */
+ badworden = Efuse_WordEnableDataWrite(padapter, startAddr+1, matched_wden, pTargetPkt->data, bPseudoTest);
+ if (badworden != 0x0F) {
+ u32 PgWriteSuccess = 0;
+ /* if write fail on some words, write these bad words again */
+ if (efuseType == EFUSE_WIFI)
+ PgWriteSuccess = Efuse_PgPacketWrite(padapter, pTargetPkt->offset, badworden, pTargetPkt->data, bPseudoTest);
+ else
+ PgWriteSuccess = Efuse_PgPacketWrite_BT(padapter, pTargetPkt->offset, badworden, pTargetPkt->data, bPseudoTest);
+
+ if (!PgWriteSuccess) {
+ bRet = false; /* write fail, return */
+ break;
+ }
+ }
+ /* partial write ok, update the target packet for later use */
+ for (i = 0; i < 4; i++) {
+ if ((matched_wden & (0x1<<i)) == 0) { /* this word has been written */
+ pTargetPkt->word_en |= (0x1<<i); /* disable the word */
+ }
+ }
+ pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
+ }
+ /* read from next header */
+ startAddr = startAddr + (curPkt.word_cnts*2) + 1;
+#endif
+ } else {
+ /* not used header, 0xff */
+ *pAddr = startAddr;
+ bRet = true;
+ break;
+ }
+ }
+
+ return bRet;
+}
+
+static u8 hal_EfusePgPacketWrite1ByteHeader(
+ struct adapter *padapter,
+ u8 efuseType,
+ u16 *pAddr,
+ struct pgpkt_struct *pTargetPkt,
+ u8 bPseudoTest
+)
+{
+ u8 pg_header = 0, tmp_header = 0;
+ u16 efuse_addr = *pAddr;
+ u8 repeatcnt = 0;
+
+ pg_header = ((pTargetPkt->offset << 4) & 0xf0) | pTargetPkt->word_en;
+
+ do {
+ efuse_OneByteWrite(padapter, efuse_addr, pg_header, bPseudoTest);
+ efuse_OneByteRead(padapter, efuse_addr, &tmp_header, bPseudoTest);
+ if (tmp_header != 0xFF)
+ break;
+ if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
+ return false;
+
+ } while (1);
+
+ if (tmp_header != pg_header)
+ return false;
+
+ *pAddr = efuse_addr;
+
+ return true;
+}
+
+static u8 hal_EfusePgPacketWrite2ByteHeader(
+ struct adapter *padapter,
+ u8 efuseType,
+ u16 *pAddr,
+ struct pgpkt_struct *pTargetPkt,
+ u8 bPseudoTest
+)
+{
+ u16 efuse_addr, efuse_max_available_len = 0;
+ u8 pg_header = 0, tmp_header = 0;
+ u8 repeatcnt = 0;
+
+ EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, &efuse_max_available_len, bPseudoTest);
+
+ efuse_addr = *pAddr;
+ if (efuse_addr >= efuse_max_available_len)
+ return false;
+
+ pg_header = ((pTargetPkt->offset & 0x07) << 5) | 0x0F;
+
+ do {
+ efuse_OneByteWrite(padapter, efuse_addr, pg_header, bPseudoTest);
+ efuse_OneByteRead(padapter, efuse_addr, &tmp_header, bPseudoTest);
+ if (tmp_header != 0xFF)
+ break;
+ if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
+ return false;
+
+ } while (1);
+
+ if (tmp_header != pg_header)
+ return false;
+
+ /* to write ext_header */
+ efuse_addr++;
+ pg_header = ((pTargetPkt->offset & 0x78) << 1) | pTargetPkt->word_en;
+
+ do {
+ efuse_OneByteWrite(padapter, efuse_addr, pg_header, bPseudoTest);
+ efuse_OneByteRead(padapter, efuse_addr, &tmp_header, bPseudoTest);
+ if (tmp_header != 0xFF)
+ break;
+ if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
+ return false;
+
+ } while (1);
+
+ if (tmp_header != pg_header) /* offset PG fail */
+ return false;
+
+ *pAddr = efuse_addr;
+
+ return true;
+}
+
+static u8 hal_EfusePgPacketWriteHeader(
+ struct adapter *padapter,
+ u8 efuseType,
+ u16 *pAddr,
+ struct pgpkt_struct *pTargetPkt,
+ u8 bPseudoTest
+)
+{
+ u8 bRet = false;
+
+ if (pTargetPkt->offset >= EFUSE_MAX_SECTION_BASE)
+ bRet = hal_EfusePgPacketWrite2ByteHeader(padapter, efuseType, pAddr, pTargetPkt, bPseudoTest);
+ else
+ bRet = hal_EfusePgPacketWrite1ByteHeader(padapter, efuseType, pAddr, pTargetPkt, bPseudoTest);
+
+ return bRet;
+}
+
+static u8 hal_EfusePgPacketWriteData(
+ struct adapter *padapter,
+ u8 efuseType,
+ u16 *pAddr,
+ struct pgpkt_struct *pTargetPkt,
+ u8 bPseudoTest
+)
+{
+ u16 efuse_addr;
+ u8 badworden;
+
+
+ efuse_addr = *pAddr;
+ badworden = Efuse_WordEnableDataWrite(padapter, efuse_addr+1, pTargetPkt->word_en, pTargetPkt->data, bPseudoTest);
+ if (badworden != 0x0F)
+ return false;
+
+ return true;
+}
+
+static s32 Hal_EfusePgPacketWrite(
+ struct adapter *padapter,
+ u8 offset,
+ u8 word_en,
+ u8 *pData,
+ bool bPseudoTest
+)
+{
+ struct pgpkt_struct targetPkt;
+ u16 startAddr = 0;
+ u8 efuseType = EFUSE_WIFI;
+
+ if (!hal_EfusePgCheckAvailableAddr(padapter, efuseType, bPseudoTest))
+ return false;
+
+ hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt);
+
+ if (!hal_EfusePartialWriteCheck(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
+ return false;
+
+ if (!hal_EfusePgPacketWriteHeader(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
+ return false;
+
+ if (!hal_EfusePgPacketWriteData(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
+ return false;
+
+ return true;
+}
+
+static bool Hal_EfusePgPacketWrite_BT(
+ struct adapter *padapter,
+ u8 offset,
+ u8 word_en,
+ u8 *pData,
+ bool bPseudoTest
+)
+{
+ struct pgpkt_struct targetPkt;
+ u16 startAddr = 0;
+ u8 efuseType = EFUSE_BT;
+
+ if (!hal_EfusePgCheckAvailableAddr(padapter, efuseType, bPseudoTest))
+ return false;
+
+ hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt);
+
+ if (!hal_EfusePartialWriteCheck(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
+ return false;
+
+ if (!hal_EfusePgPacketWriteHeader(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
+ return false;
+
+ if (!hal_EfusePgPacketWriteData(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
+ return false;
+
+ return true;
+}
+
+static struct hal_version ReadChipVersion8723B(struct adapter *padapter)
+{
+ u32 value32;
+ struct hal_version ChipVersion;
+ struct hal_com_data *pHalData;
+
+/* YJ, TODO, move read chip type here */
+ pHalData = GET_HAL_DATA(padapter);
+
+ value32 = rtw_read32(padapter, REG_SYS_CFG);
+ ChipVersion.ICType = CHIP_8723B;
+ ChipVersion.ChipType = ((value32 & RTL_ID) ? TEST_CHIP : NORMAL_CHIP);
+ ChipVersion.VendorType = ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : CHIP_VENDOR_TSMC);
+ ChipVersion.CUTVersion = (value32 & CHIP_VER_RTL_MASK)>>CHIP_VER_RTL_SHIFT; /* IC version (CUT) */
+
+ /* For regulator mode. by tynli. 2011.01.14 */
+ pHalData->RegulatorMode = ((value32 & SPS_SEL) ? RT_LDO_REGULATOR : RT_SWITCHING_REGULATOR);
+
+ value32 = rtw_read32(padapter, REG_GPIO_OUTSTS);
+ ChipVersion.ROMVer = ((value32 & RF_RL_ID) >> 20); /* ROM code version. */
+
+ /* For multi-function consideration. Added by Roger, 2010.10.06. */
+ pHalData->MultiFunc = RT_MULTI_FUNC_NONE;
+ value32 = rtw_read32(padapter, REG_MULTI_FUNC_CTRL);
+ pHalData->MultiFunc |= ((value32 & WL_FUNC_EN) ? RT_MULTI_FUNC_WIFI : 0);
+ pHalData->MultiFunc |= ((value32 & BT_FUNC_EN) ? RT_MULTI_FUNC_BT : 0);
+ pHalData->MultiFunc |= ((value32 & GPS_FUNC_EN) ? RT_MULTI_FUNC_GPS : 0);
+ pHalData->PolarityCtl = ((value32 & WL_HWPDN_SL) ? RT_POLARITY_HIGH_ACT : RT_POLARITY_LOW_ACT);
+#if 1
+ dump_chip_info(ChipVersion);
+#endif
+ pHalData->VersionID = ChipVersion;
+
+ return ChipVersion;
+}
+
+static void rtl8723b_read_chip_version(struct adapter *padapter)
+{
+ ReadChipVersion8723B(padapter);
+}
+
+void rtl8723b_InitBeaconParameters(struct adapter *padapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ u16 val16;
+ u8 val8;
+
+
+ val8 = DIS_TSF_UDT;
+ val16 = val8 | (val8 << 8); /* port0 and port1 */
+
+ /* Enable prot0 beacon function for PSTDMA */
+ val16 |= EN_BCN_FUNCTION;
+
+ rtw_write16(padapter, REG_BCN_CTRL, val16);
+
+ /* TODO: Remove these magic number */
+ rtw_write16(padapter, REG_TBTT_PROHIBIT, 0x6404);/* ms */
+ /* Firmware will control REG_DRVERLYINT when power saving is enable, */
+ /* so don't set this register on STA mode. */
+ if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == false)
+ rtw_write8(padapter, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME_8723B); /* 5ms */
+ rtw_write8(padapter, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME_8723B); /* 2ms */
+
+ /* Suggested by designer timchen. Change beacon AIFS to the largest number */
+ /* beacause test chip does not contension before sending beacon. by tynli. 2009.11.03 */
+ rtw_write16(padapter, REG_BCNTCFG, 0x660F);
+
+ pHalData->RegBcnCtrlVal = rtw_read8(padapter, REG_BCN_CTRL);
+ pHalData->RegTxPause = rtw_read8(padapter, REG_TXPAUSE);
+ pHalData->RegFwHwTxQCtrl = rtw_read8(padapter, REG_FWHW_TXQ_CTRL+2);
+ pHalData->RegReg542 = rtw_read8(padapter, REG_TBTT_PROHIBIT+2);
+ pHalData->RegCR_1 = rtw_read8(padapter, REG_CR+1);
+}
+
+void _InitBurstPktLen_8723BS(struct adapter *Adapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+
+ rtw_write8(Adapter, 0x4c7, rtw_read8(Adapter, 0x4c7)|BIT(7)); /* enable single pkt ampdu */
+ rtw_write8(Adapter, REG_RX_PKT_LIMIT_8723B, 0x18); /* for VHT packet length 11K */
+ rtw_write8(Adapter, REG_MAX_AGGR_NUM_8723B, 0x1F);
+ rtw_write8(Adapter, REG_PIFS_8723B, 0x00);
+ rtw_write8(Adapter, REG_FWHW_TXQ_CTRL_8723B, rtw_read8(Adapter, REG_FWHW_TXQ_CTRL)&(~BIT(7)));
+ if (pHalData->AMPDUBurstMode)
+ rtw_write8(Adapter, REG_AMPDU_BURST_MODE_8723B, 0x5F);
+ rtw_write8(Adapter, REG_AMPDU_MAX_TIME_8723B, 0x70);
+
+ /* ARFB table 9 for 11ac 5G 2SS */
+ rtw_write32(Adapter, REG_ARFR0_8723B, 0x00000010);
+ if (IS_NORMAL_CHIP(pHalData->VersionID))
+ rtw_write32(Adapter, REG_ARFR0_8723B+4, 0xfffff000);
+ else
+ rtw_write32(Adapter, REG_ARFR0_8723B+4, 0x3e0ff000);
+
+ /* ARFB table 10 for 11ac 5G 1SS */
+ rtw_write32(Adapter, REG_ARFR1_8723B, 0x00000010);
+ rtw_write32(Adapter, REG_ARFR1_8723B+4, 0x003ff000);
+}
+
+static void ResumeTxBeacon(struct adapter *padapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+
+ pHalData->RegFwHwTxQCtrl |= BIT(6);
+ rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl);
+ rtw_write8(padapter, REG_TBTT_PROHIBIT+1, 0xff);
+ pHalData->RegReg542 |= BIT(0);
+ rtw_write8(padapter, REG_TBTT_PROHIBIT+2, pHalData->RegReg542);
+}
+
+static void StopTxBeacon(struct adapter *padapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+
+ pHalData->RegFwHwTxQCtrl &= ~BIT(6);
+ rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl);
+ rtw_write8(padapter, REG_TBTT_PROHIBIT+1, 0x64);
+ pHalData->RegReg542 &= ~BIT(0);
+ rtw_write8(padapter, REG_TBTT_PROHIBIT+2, pHalData->RegReg542);
+
+ CheckFwRsvdPageContent(padapter); /* 2010.06.23. Added by tynli. */
+}
+
+static void _BeaconFunctionEnable(struct adapter *padapter, u8 Enable, u8 Linked)
+{
+ rtw_write8(padapter, REG_BCN_CTRL, DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_BCNQ_SUB);
+ rtw_write8(padapter, REG_RD_CTRL+1, 0x6F);
+}
+
+static void rtl8723b_SetBeaconRelatedRegisters(struct adapter *padapter)
+{
+ u8 val8;
+ u32 value32;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ u32 bcn_ctrl_reg;
+
+ /* reset TSF, enable update TSF, correcting TSF On Beacon */
+
+ /* REG_BCN_INTERVAL */
+ /* REG_BCNDMATIM */
+ /* REG_ATIMWND */
+ /* REG_TBTT_PROHIBIT */
+ /* REG_DRVERLYINT */
+ /* REG_BCN_MAX_ERR */
+ /* REG_BCNTCFG (0x510) */
+ /* REG_DUAL_TSF_RST */
+ /* REG_BCN_CTRL (0x550) */
+
+
+ bcn_ctrl_reg = REG_BCN_CTRL;
+
+ /* */
+ /* ATIM window */
+ /* */
+ rtw_write16(padapter, REG_ATIMWND, 2);
+
+ /* */
+ /* Beacon interval (in unit of TU). */
+ /* */
+ rtw_write16(padapter, REG_BCN_INTERVAL, pmlmeinfo->bcn_interval);
+
+ rtl8723b_InitBeaconParameters(padapter);
+
+ rtw_write8(padapter, REG_SLOT, 0x09);
+
+ /* */
+ /* Reset TSF Timer to zero, added by Roger. 2008.06.24 */
+ /* */
+ value32 = rtw_read32(padapter, REG_TCR);
+ value32 &= ~TSFRST;
+ rtw_write32(padapter, REG_TCR, value32);
+
+ value32 |= TSFRST;
+ rtw_write32(padapter, REG_TCR, value32);
+
+ /* NOTE: Fix test chip's bug (about contention windows's randomness) */
+ if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE) == true) {
+ rtw_write8(padapter, REG_RXTSF_OFFSET_CCK, 0x50);
+ rtw_write8(padapter, REG_RXTSF_OFFSET_OFDM, 0x50);
+ }
+
+ _BeaconFunctionEnable(padapter, true, true);
+
+ ResumeTxBeacon(padapter);
+ val8 = rtw_read8(padapter, bcn_ctrl_reg);
+ val8 |= DIS_BCNQ_SUB;
+ rtw_write8(padapter, bcn_ctrl_reg, val8);
+}
+
+static void rtl8723b_GetHalODMVar(
+ struct adapter *Adapter,
+ enum hal_odm_variable eVariable,
+ void *pValue1,
+ void *pValue2
+)
+{
+ GetHalODMVar(Adapter, eVariable, pValue1, pValue2);
+}
+
+static void rtl8723b_SetHalODMVar(
+ struct adapter *Adapter,
+ enum hal_odm_variable eVariable,
+ void *pValue1,
+ bool bSet
+)
+{
+ SetHalODMVar(Adapter, eVariable, pValue1, bSet);
+}
+
+static void hal_notch_filter_8723b(struct adapter *adapter, bool enable)
+{
+ if (enable)
+ rtw_write8(adapter, rOFDM0_RxDSP+1, rtw_read8(adapter, rOFDM0_RxDSP+1) | BIT1);
+ else
+ rtw_write8(adapter, rOFDM0_RxDSP+1, rtw_read8(adapter, rOFDM0_RxDSP+1) & ~BIT1);
+}
+
+static void UpdateHalRAMask8723B(struct adapter *padapter, u32 mac_id, u8 rssi_level)
+{
+ u32 mask, rate_bitmap;
+ u8 shortGIrate = false;
+ struct sta_info *psta;
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct dm_priv *pdmpriv = &pHalData->dmpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+
+ if (mac_id >= NUM_STA) /* CAM_SIZE */
+ return;
+
+ psta = pmlmeinfo->FW_sta_info[mac_id].psta;
+ if (!psta)
+ return;
+
+ shortGIrate = query_ra_short_GI(psta);
+
+ mask = psta->ra_mask;
+
+ rate_bitmap = 0xffffffff;
+ rate_bitmap = ODM_Get_Rate_Bitmap(&pHalData->odmpriv, mac_id, mask, rssi_level);
+
+ mask &= rate_bitmap;
+
+ rate_bitmap = hal_btcoex_GetRaMask(padapter);
+ mask &= ~rate_bitmap;
+
+ if (pHalData->fw_ractrl) {
+ rtl8723b_set_FwMacIdConfig_cmd(padapter, mac_id, psta->raid, psta->bw_mode, shortGIrate, mask);
+ }
+
+ /* set correct initial date rate for each mac_id */
+ pdmpriv->INIDATA_RATE[mac_id] = psta->init_rate;
+}
+
+
+void rtl8723b_set_hal_ops(struct hal_ops *pHalFunc)
+{
+ pHalFunc->free_hal_data = &rtl8723b_free_hal_data;
+
+ pHalFunc->dm_init = &rtl8723b_init_dm_priv;
+
+ pHalFunc->read_chip_version = &rtl8723b_read_chip_version;
+
+ pHalFunc->UpdateRAMaskHandler = &UpdateHalRAMask8723B;
+
+ pHalFunc->set_bwmode_handler = &PHY_SetBWMode8723B;
+ pHalFunc->set_channel_handler = &PHY_SwChnl8723B;
+ pHalFunc->set_chnl_bw_handler = &PHY_SetSwChnlBWMode8723B;
+
+ pHalFunc->set_tx_power_level_handler = &PHY_SetTxPowerLevel8723B;
+ pHalFunc->get_tx_power_level_handler = &PHY_GetTxPowerLevel8723B;
+
+ pHalFunc->hal_dm_watchdog = &rtl8723b_HalDmWatchDog;
+ pHalFunc->hal_dm_watchdog_in_lps = &rtl8723b_HalDmWatchDog_in_LPS;
+
+
+ pHalFunc->SetBeaconRelatedRegistersHandler = &rtl8723b_SetBeaconRelatedRegisters;
+
+ pHalFunc->Add_RateATid = &rtl8723b_Add_RateATid;
+
+ pHalFunc->run_thread = &rtl8723b_start_thread;
+ pHalFunc->cancel_thread = &rtl8723b_stop_thread;
+
+ pHalFunc->read_bbreg = &PHY_QueryBBReg_8723B;
+ pHalFunc->write_bbreg = &PHY_SetBBReg_8723B;
+ pHalFunc->read_rfreg = &PHY_QueryRFReg_8723B;
+ pHalFunc->write_rfreg = &PHY_SetRFReg_8723B;
+
+ /* Efuse related function */
+ pHalFunc->BTEfusePowerSwitch = &Hal_BT_EfusePowerSwitch;
+ pHalFunc->EfusePowerSwitch = &Hal_EfusePowerSwitch;
+ pHalFunc->ReadEFuse = &Hal_ReadEFuse;
+ pHalFunc->EFUSEGetEfuseDefinition = &Hal_GetEfuseDefinition;
+ pHalFunc->EfuseGetCurrentSize = &Hal_EfuseGetCurrentSize;
+ pHalFunc->Efuse_PgPacketRead = &Hal_EfusePgPacketRead;
+ pHalFunc->Efuse_PgPacketWrite = &Hal_EfusePgPacketWrite;
+ pHalFunc->Efuse_WordEnableDataWrite = &Hal_EfuseWordEnableDataWrite;
+ pHalFunc->Efuse_PgPacketWrite_BT = &Hal_EfusePgPacketWrite_BT;
+
+ pHalFunc->GetHalODMVarHandler = &rtl8723b_GetHalODMVar;
+ pHalFunc->SetHalODMVarHandler = &rtl8723b_SetHalODMVar;
+
+ pHalFunc->xmit_thread_handler = &hal_xmit_handler;
+ pHalFunc->hal_notch_filter = &hal_notch_filter_8723b;
+
+ pHalFunc->c2h_handler = c2h_handler_8723b;
+ pHalFunc->c2h_id_filter_ccx = c2h_id_filter_ccx_8723b;
+
+ pHalFunc->fill_h2c_cmd = &FillH2CCmd8723B;
+}
+
+void rtl8723b_InitAntenna_Selection(struct adapter *padapter)
+{
+ u8 val;
+
+ val = rtw_read8(padapter, REG_LEDCFG2);
+ /* Let 8051 take control antenna setting */
+ val |= BIT(7); /* DPDT_SEL_EN, 0x4C[23] */
+ rtw_write8(padapter, REG_LEDCFG2, val);
+}
+
+void rtl8723b_init_default_value(struct adapter *padapter)
+{
+ struct hal_com_data *pHalData;
+ struct dm_priv *pdmpriv;
+ u8 i;
+
+
+ pHalData = GET_HAL_DATA(padapter);
+ pdmpriv = &pHalData->dmpriv;
+
+ padapter->registrypriv.wireless_mode = WIRELESS_11BG_24N;
+
+ /* init default value */
+ pHalData->fw_ractrl = false;
+ pHalData->bIQKInitialized = false;
+ if (!adapter_to_pwrctl(padapter)->bkeepfwalive)
+ pHalData->LastHMEBoxNum = 0;
+
+ pHalData->bIQKInitialized = false;
+
+ /* init dm default value */
+ pdmpriv->TM_Trigger = 0;/* for IQK */
+/* pdmpriv->binitialized = false; */
+/* pdmpriv->prv_traffic_idx = 3; */
+/* pdmpriv->initialize = 0; */
+
+ pdmpriv->ThermalValue_HP_index = 0;
+ for (i = 0; i < HP_THERMAL_NUM; i++)
+ pdmpriv->ThermalValue_HP[i] = 0;
+
+ /* init Efuse variables */
+ pHalData->EfuseUsedBytes = 0;
+ pHalData->EfuseUsedPercentage = 0;
+#ifdef HAL_EFUSE_MEMORY
+ pHalData->EfuseHal.fakeEfuseBank = 0;
+ pHalData->EfuseHal.fakeEfuseUsedBytes = 0;
+ memset(pHalData->EfuseHal.fakeEfuseContent, 0xFF, EFUSE_MAX_HW_SIZE);
+ memset(pHalData->EfuseHal.fakeEfuseInitMap, 0xFF, EFUSE_MAX_MAP_LEN);
+ memset(pHalData->EfuseHal.fakeEfuseModifiedMap, 0xFF, EFUSE_MAX_MAP_LEN);
+ pHalData->EfuseHal.BTEfuseUsedBytes = 0;
+ pHalData->EfuseHal.BTEfuseUsedPercentage = 0;
+ memset(pHalData->EfuseHal.BTEfuseContent, 0xFF, EFUSE_MAX_BT_BANK*EFUSE_MAX_HW_SIZE);
+ memset(pHalData->EfuseHal.BTEfuseInitMap, 0xFF, EFUSE_BT_MAX_MAP_LEN);
+ memset(pHalData->EfuseHal.BTEfuseModifiedMap, 0xFF, EFUSE_BT_MAX_MAP_LEN);
+ pHalData->EfuseHal.fakeBTEfuseUsedBytes = 0;
+ memset(pHalData->EfuseHal.fakeBTEfuseContent, 0xFF, EFUSE_MAX_BT_BANK*EFUSE_MAX_HW_SIZE);
+ memset(pHalData->EfuseHal.fakeBTEfuseInitMap, 0xFF, EFUSE_BT_MAX_MAP_LEN);
+ memset(pHalData->EfuseHal.fakeBTEfuseModifiedMap, 0xFF, EFUSE_BT_MAX_MAP_LEN);
+#endif
+}
+
+u8 GetEEPROMSize8723B(struct adapter *padapter)
+{
+ u8 size = 0;
+ u32 cr;
+
+ cr = rtw_read16(padapter, REG_9346CR);
+ /* 6: EEPROM used is 93C46, 4: boot from E-Fuse. */
+ size = (cr & BOOT_FROM_EEPROM) ? 6 : 4;
+
+ return size;
+}
+
+/* */
+/* */
+/* LLT R/W/Init function */
+/* */
+/* */
+s32 rtl8723b_InitLLTTable(struct adapter *padapter)
+{
+ unsigned long start, passing_time;
+ u32 val32;
+ s32 ret;
+
+
+ ret = _FAIL;
+
+ val32 = rtw_read32(padapter, REG_AUTO_LLT);
+ val32 |= BIT_AUTO_INIT_LLT;
+ rtw_write32(padapter, REG_AUTO_LLT, val32);
+
+ start = jiffies;
+
+ do {
+ val32 = rtw_read32(padapter, REG_AUTO_LLT);
+ if (!(val32 & BIT_AUTO_INIT_LLT)) {
+ ret = _SUCCESS;
+ break;
+ }
+
+ passing_time = jiffies_to_msecs(jiffies - start);
+ if (passing_time > 1000)
+ break;
+
+ msleep(1);
+ } while (1);
+
+ return ret;
+}
+
+static void hal_get_chnl_group_8723b(u8 channel, u8 *group)
+{
+ if (1 <= channel && channel <= 2)
+ *group = 0;
+ else if (3 <= channel && channel <= 5)
+ *group = 1;
+ else if (6 <= channel && channel <= 8)
+ *group = 2;
+ else if (9 <= channel && channel <= 11)
+ *group = 3;
+ else if (12 <= channel && channel <= 14)
+ *group = 4;
+}
+
+void Hal_InitPGData(struct adapter *padapter, u8 *PROMContent)
+{
+ struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
+
+ if (!pEEPROM->bautoload_fail_flag) { /* autoload OK. */
+ if (!pEEPROM->EepromOrEfuse) {
+ /* Read EFUSE real map to shadow. */
+ EFUSE_ShadowMapUpdate(padapter, EFUSE_WIFI, false);
+ memcpy((void *)PROMContent, (void *)pEEPROM->efuse_eeprom_data, HWSET_MAX_SIZE_8723B);
+ }
+ } else {/* autoload fail */
+ if (!pEEPROM->EepromOrEfuse)
+ EFUSE_ShadowMapUpdate(padapter, EFUSE_WIFI, false);
+ memcpy((void *)PROMContent, (void *)pEEPROM->efuse_eeprom_data, HWSET_MAX_SIZE_8723B);
+ }
+}
+
+void Hal_EfuseParseIDCode(struct adapter *padapter, u8 *hwinfo)
+{
+ struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
+/* struct hal_com_data *pHalData = GET_HAL_DATA(padapter); */
+ u16 EEPROMId;
+
+
+ /* Checl 0x8129 again for making sure autoload status!! */
+ EEPROMId = le16_to_cpu(*((__le16 *)hwinfo));
+ if (EEPROMId != RTL_EEPROM_ID) {
+ pEEPROM->bautoload_fail_flag = true;
+ } else
+ pEEPROM->bautoload_fail_flag = false;
+}
+
+static void Hal_ReadPowerValueFromPROM_8723B(
+ struct adapter *Adapter,
+ struct TxPowerInfo24G *pwrInfo24G,
+ u8 *PROMContent,
+ bool AutoLoadFail
+)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+ u32 rfPath, eeAddr = EEPROM_TX_PWR_INX_8723B, group, TxCount = 0;
+
+ memset(pwrInfo24G, 0, sizeof(struct TxPowerInfo24G));
+
+ if (0xFF == PROMContent[eeAddr+1])
+ AutoLoadFail = true;
+
+ if (AutoLoadFail) {
+ for (rfPath = 0; rfPath < MAX_RF_PATH; rfPath++) {
+ /* 2.4G default value */
+ for (group = 0; group < MAX_CHNL_GROUP_24G; group++) {
+ pwrInfo24G->IndexCCK_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
+ pwrInfo24G->IndexBW40_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
+ }
+
+ for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
+ if (TxCount == 0) {
+ pwrInfo24G->BW20_Diff[rfPath][0] = EEPROM_DEFAULT_24G_HT20_DIFF;
+ pwrInfo24G->OFDM_Diff[rfPath][0] = EEPROM_DEFAULT_24G_OFDM_DIFF;
+ } else {
+ pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
+ pwrInfo24G->BW40_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
+ pwrInfo24G->CCK_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
+ pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
+ }
+ }
+ }
+
+ return;
+ }
+
+ pHalData->bTXPowerDataReadFromEEPORM = true; /* YJ, move, 120316 */
+
+ for (rfPath = 0; rfPath < MAX_RF_PATH; rfPath++) {
+ /* 2 2.4G default value */
+ for (group = 0; group < MAX_CHNL_GROUP_24G; group++) {
+ pwrInfo24G->IndexCCK_Base[rfPath][group] = PROMContent[eeAddr++];
+ if (pwrInfo24G->IndexCCK_Base[rfPath][group] == 0xFF)
+ pwrInfo24G->IndexCCK_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
+ }
+
+ for (group = 0; group < MAX_CHNL_GROUP_24G-1; group++) {
+ pwrInfo24G->IndexBW40_Base[rfPath][group] = PROMContent[eeAddr++];
+ if (pwrInfo24G->IndexBW40_Base[rfPath][group] == 0xFF)
+ pwrInfo24G->IndexBW40_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
+ }
+
+ for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
+ if (TxCount == 0) {
+ pwrInfo24G->BW40_Diff[rfPath][TxCount] = 0;
+ if (PROMContent[eeAddr] == 0xFF)
+ pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_24G_HT20_DIFF;
+ else {
+ pwrInfo24G->BW20_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0xf0)>>4;
+ if (pwrInfo24G->BW20_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
+ pwrInfo24G->BW20_Diff[rfPath][TxCount] |= 0xF0;
+ }
+
+ if (PROMContent[eeAddr] == 0xFF)
+ pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_24G_OFDM_DIFF;
+ else {
+ pwrInfo24G->OFDM_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0x0f);
+ if (pwrInfo24G->OFDM_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
+ pwrInfo24G->OFDM_Diff[rfPath][TxCount] |= 0xF0;
+ }
+ pwrInfo24G->CCK_Diff[rfPath][TxCount] = 0;
+ eeAddr++;
+ } else {
+ if (PROMContent[eeAddr] == 0xFF)
+ pwrInfo24G->BW40_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
+ else {
+ pwrInfo24G->BW40_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0xf0)>>4;
+ if (pwrInfo24G->BW40_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
+ pwrInfo24G->BW40_Diff[rfPath][TxCount] |= 0xF0;
+ }
+
+ if (PROMContent[eeAddr] == 0xFF)
+ pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
+ else {
+ pwrInfo24G->BW20_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0x0f);
+ if (pwrInfo24G->BW20_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
+ pwrInfo24G->BW20_Diff[rfPath][TxCount] |= 0xF0;
+ }
+ eeAddr++;
+
+ if (PROMContent[eeAddr] == 0xFF)
+ pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
+ else {
+ pwrInfo24G->OFDM_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0xf0)>>4;
+ if (pwrInfo24G->OFDM_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
+ pwrInfo24G->OFDM_Diff[rfPath][TxCount] |= 0xF0;
+ }
+
+ if (PROMContent[eeAddr] == 0xFF)
+ pwrInfo24G->CCK_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
+ else {
+ pwrInfo24G->CCK_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0x0f);
+ if (pwrInfo24G->CCK_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
+ pwrInfo24G->CCK_Diff[rfPath][TxCount] |= 0xF0;
+ }
+ eeAddr++;
+ }
+ }
+ }
+}
+
+
+void Hal_EfuseParseTxPowerInfo_8723B(
+ struct adapter *padapter, u8 *PROMContent, bool AutoLoadFail
+)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct TxPowerInfo24G pwrInfo24G;
+ u8 rfPath, ch, TxCount = 1;
+
+ Hal_ReadPowerValueFromPROM_8723B(padapter, &pwrInfo24G, PROMContent, AutoLoadFail);
+ for (rfPath = 0 ; rfPath < MAX_RF_PATH ; rfPath++) {
+ for (ch = 0 ; ch < CHANNEL_MAX_NUMBER; ch++) {
+ u8 group = 0;
+
+ hal_get_chnl_group_8723b(ch + 1, &group);
+
+ if (ch == 14-1) {
+ pHalData->Index24G_CCK_Base[rfPath][ch] = pwrInfo24G.IndexCCK_Base[rfPath][5];
+ pHalData->Index24G_BW40_Base[rfPath][ch] = pwrInfo24G.IndexBW40_Base[rfPath][group];
+ } else {
+ pHalData->Index24G_CCK_Base[rfPath][ch] = pwrInfo24G.IndexCCK_Base[rfPath][group];
+ pHalData->Index24G_BW40_Base[rfPath][ch] = pwrInfo24G.IndexBW40_Base[rfPath][group];
+ }
+ }
+
+ for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
+ pHalData->CCK_24G_Diff[rfPath][TxCount] = pwrInfo24G.CCK_Diff[rfPath][TxCount];
+ pHalData->OFDM_24G_Diff[rfPath][TxCount] = pwrInfo24G.OFDM_Diff[rfPath][TxCount];
+ pHalData->BW20_24G_Diff[rfPath][TxCount] = pwrInfo24G.BW20_Diff[rfPath][TxCount];
+ pHalData->BW40_24G_Diff[rfPath][TxCount] = pwrInfo24G.BW40_Diff[rfPath][TxCount];
+ }
+ }
+
+ /* 2010/10/19 MH Add Regulator recognize for CU. */
+ if (!AutoLoadFail) {
+ pHalData->EEPROMRegulatory = (PROMContent[EEPROM_RF_BOARD_OPTION_8723B]&0x7); /* bit0~2 */
+ if (PROMContent[EEPROM_RF_BOARD_OPTION_8723B] == 0xFF)
+ pHalData->EEPROMRegulatory = (EEPROM_DEFAULT_BOARD_OPTION&0x7); /* bit0~2 */
+ } else
+ pHalData->EEPROMRegulatory = 0;
+}
+
+void Hal_EfuseParseBTCoexistInfo_8723B(
+ struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
+)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ u8 tempval;
+ u32 tmpu4;
+
+ if (!AutoLoadFail) {
+ tmpu4 = rtw_read32(padapter, REG_MULTI_FUNC_CTRL);
+ if (tmpu4 & BT_FUNC_EN)
+ pHalData->EEPROMBluetoothCoexist = true;
+ else
+ pHalData->EEPROMBluetoothCoexist = false;
+
+ pHalData->EEPROMBluetoothType = BT_RTL8723B;
+
+ tempval = hwinfo[EEPROM_RF_BT_SETTING_8723B];
+ if (tempval != 0xFF) {
+ pHalData->EEPROMBluetoothAntNum = tempval & BIT(0);
+ /* EFUSE_0xC3[6] == 0, S1(Main)-RF_PATH_A; */
+ /* EFUSE_0xC3[6] == 1, S0(Aux)-RF_PATH_B */
+ pHalData->ant_path = (tempval & BIT(6))? RF_PATH_B : RF_PATH_A;
+ } else {
+ pHalData->EEPROMBluetoothAntNum = Ant_x1;
+ if (pHalData->PackageType == PACKAGE_QFN68)
+ pHalData->ant_path = RF_PATH_B;
+ else
+ pHalData->ant_path = RF_PATH_A;
+ }
+ } else {
+ pHalData->EEPROMBluetoothCoexist = false;
+ pHalData->EEPROMBluetoothType = BT_RTL8723B;
+ pHalData->EEPROMBluetoothAntNum = Ant_x1;
+ pHalData->ant_path = RF_PATH_A;
+ }
+
+ if (padapter->registrypriv.ant_num > 0) {
+ switch (padapter->registrypriv.ant_num) {
+ case 1:
+ pHalData->EEPROMBluetoothAntNum = Ant_x1;
+ break;
+ case 2:
+ pHalData->EEPROMBluetoothAntNum = Ant_x2;
+ break;
+ default:
+ break;
+ }
+ }
+
+ hal_btcoex_SetBTCoexist(padapter, pHalData->EEPROMBluetoothCoexist);
+ hal_btcoex_SetChipType(padapter, pHalData->EEPROMBluetoothType);
+ hal_btcoex_SetPgAntNum(padapter, pHalData->EEPROMBluetoothAntNum == Ant_x2 ? 2 : 1);
+ if (pHalData->EEPROMBluetoothAntNum == Ant_x1)
+ hal_btcoex_SetSingleAntPath(padapter, pHalData->ant_path);
+}
+
+void Hal_EfuseParseEEPROMVer_8723B(
+ struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
+)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+
+ if (!AutoLoadFail)
+ pHalData->EEPROMVersion = hwinfo[EEPROM_VERSION_8723B];
+ else
+ pHalData->EEPROMVersion = 1;
+}
+
+
+
+void Hal_EfuseParsePackageType_8723B(
+ struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
+)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ u8 package;
+ u8 efuseContent;
+
+ Efuse_PowerSwitch(padapter, false, true);
+ efuse_OneByteRead(padapter, 0x1FB, &efuseContent, false);
+ Efuse_PowerSwitch(padapter, false, false);
+
+ package = efuseContent & 0x7;
+ switch (package) {
+ case 0x4:
+ pHalData->PackageType = PACKAGE_TFBGA79;
+ break;
+ case 0x5:
+ pHalData->PackageType = PACKAGE_TFBGA90;
+ break;
+ case 0x6:
+ pHalData->PackageType = PACKAGE_QFN68;
+ break;
+ case 0x7:
+ pHalData->PackageType = PACKAGE_TFBGA80;
+ break;
+
+ default:
+ pHalData->PackageType = PACKAGE_DEFAULT;
+ break;
+ }
+}
+
+
+void Hal_EfuseParseVoltage_8723B(
+ struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
+)
+{
+ struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
+
+ /* memcpy(pEEPROM->adjuseVoltageVal, &hwinfo[EEPROM_Voltage_ADDR_8723B], 1); */
+ pEEPROM->adjuseVoltageVal = (hwinfo[EEPROM_Voltage_ADDR_8723B] & 0xf0) >> 4;
+}
+
+void Hal_EfuseParseChnlPlan_8723B(
+ struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
+)
+{
+ padapter->mlmepriv.ChannelPlan = hal_com_config_channel_plan(
+ padapter,
+ hwinfo ? hwinfo[EEPROM_ChannelPlan_8723B] : 0xFF,
+ padapter->registrypriv.channel_plan,
+ RT_CHANNEL_DOMAIN_WORLD_NULL,
+ AutoLoadFail
+ );
+
+ Hal_ChannelPlanToRegulation(padapter, padapter->mlmepriv.ChannelPlan);
+}
+
+void Hal_EfuseParseCustomerID_8723B(
+ struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
+)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+
+ if (!AutoLoadFail)
+ pHalData->EEPROMCustomerID = hwinfo[EEPROM_CustomID_8723B];
+ else
+ pHalData->EEPROMCustomerID = 0;
+}
+
+void Hal_EfuseParseAntennaDiversity_8723B(
+ struct adapter *padapter,
+ u8 *hwinfo,
+ bool AutoLoadFail
+)
+{
+}
+
+void Hal_EfuseParseXtal_8723B(
+ struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
+)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+
+ if (!AutoLoadFail) {
+ pHalData->CrystalCap = hwinfo[EEPROM_XTAL_8723B];
+ if (pHalData->CrystalCap == 0xFF)
+ pHalData->CrystalCap = EEPROM_Default_CrystalCap_8723B; /* what value should 8812 set? */
+ } else
+ pHalData->CrystalCap = EEPROM_Default_CrystalCap_8723B;
+}
+
+
+void Hal_EfuseParseThermalMeter_8723B(
+ struct adapter *padapter, u8 *PROMContent, u8 AutoLoadFail
+)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+
+ /* */
+ /* ThermalMeter from EEPROM */
+ /* */
+ if (!AutoLoadFail)
+ pHalData->EEPROMThermalMeter = PROMContent[EEPROM_THERMAL_METER_8723B];
+ else
+ pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter_8723B;
+
+ if ((pHalData->EEPROMThermalMeter == 0xff) || AutoLoadFail) {
+ pHalData->bAPKThermalMeterIgnore = true;
+ pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter_8723B;
+ }
+}
+
+
+void Hal_ReadRFGainOffset(
+ struct adapter *Adapter, u8 *PROMContent, bool AutoloadFail
+)
+{
+ /* */
+ /* BB_RF Gain Offset from EEPROM */
+ /* */
+
+ if (!AutoloadFail) {
+ Adapter->eeprompriv.EEPROMRFGainOffset = PROMContent[EEPROM_RF_GAIN_OFFSET];
+ Adapter->eeprompriv.EEPROMRFGainVal = EFUSE_Read1Byte(Adapter, EEPROM_RF_GAIN_VAL);
+ } else {
+ Adapter->eeprompriv.EEPROMRFGainOffset = 0;
+ Adapter->eeprompriv.EEPROMRFGainVal = 0xFF;
+ }
+}
+
+u8 BWMapping_8723B(struct adapter *Adapter, struct pkt_attrib *pattrib)
+{
+ u8 BWSettingOfDesc = 0;
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+
+ if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_40) {
+ if (pattrib->bwmode == CHANNEL_WIDTH_40)
+ BWSettingOfDesc = 1;
+ else
+ BWSettingOfDesc = 0;
+ } else
+ BWSettingOfDesc = 0;
+
+ /* if (pTcb->bBTTxPacket) */
+ /* BWSettingOfDesc = 0; */
+
+ return BWSettingOfDesc;
+}
+
+u8 SCMapping_8723B(struct adapter *Adapter, struct pkt_attrib *pattrib)
+{
+ u8 SCSettingOfDesc = 0;
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+
+ if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_40) {
+ if (pattrib->bwmode == CHANNEL_WIDTH_40) {
+ SCSettingOfDesc = HT_DATA_SC_DONOT_CARE;
+ } else if (pattrib->bwmode == CHANNEL_WIDTH_20) {
+ if (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER) {
+ SCSettingOfDesc = HT_DATA_SC_20_UPPER_OF_40MHZ;
+ } else if (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) {
+ SCSettingOfDesc = HT_DATA_SC_20_LOWER_OF_40MHZ;
+ } else {
+ SCSettingOfDesc = HT_DATA_SC_DONOT_CARE;
+ }
+ }
+ } else {
+ SCSettingOfDesc = HT_DATA_SC_DONOT_CARE;
+ }
+
+ return SCSettingOfDesc;
+}
+
+static void rtl8723b_cal_txdesc_chksum(struct tx_desc *ptxdesc)
+{
+ u16 *usPtr = (u16 *)ptxdesc;
+ u32 count;
+ u32 index;
+ u16 checksum = 0;
+
+
+ /* Clear first */
+ ptxdesc->txdw7 &= cpu_to_le32(0xffff0000);
+
+ /* checksume is always calculated by first 32 bytes, */
+ /* and it doesn't depend on TX DESC length. */
+ /* Thomas, Lucas@SD4, 20130515 */
+ count = 16;
+
+ for (index = 0; index < count; index++) {
+ checksum |= le16_to_cpu(*(__le16 *)(usPtr + index));
+ }
+
+ ptxdesc->txdw7 |= cpu_to_le32(checksum & 0x0000ffff);
+}
+
+static u8 fill_txdesc_sectype(struct pkt_attrib *pattrib)
+{
+ u8 sectype = 0;
+ if ((pattrib->encrypt > 0) && !pattrib->bswenc) {
+ switch (pattrib->encrypt) {
+ /* SEC_TYPE */
+ case _WEP40_:
+ case _WEP104_:
+ case _TKIP_:
+ case _TKIP_WTMIC_:
+ sectype = 1;
+ break;
+
+ case _AES_:
+ sectype = 3;
+ break;
+
+ case _NO_PRIVACY_:
+ default:
+ break;
+ }
+ }
+ return sectype;
+}
+
+static void fill_txdesc_vcs_8723b(struct adapter *padapter, struct pkt_attrib *pattrib, struct txdesc_8723b *ptxdesc)
+{
+ if (pattrib->vcs_mode) {
+ switch (pattrib->vcs_mode) {
+ case RTS_CTS:
+ ptxdesc->rtsen = 1;
+ /* ENABLE HW RTS */
+ ptxdesc->hw_rts_en = 1;
+ break;
+
+ case CTS_TO_SELF:
+ ptxdesc->cts2self = 1;
+ break;
+
+ case NONE_VCS:
+ default:
+ break;
+ }
+
+ ptxdesc->rtsrate = 8; /* RTS Rate =24M */
+ ptxdesc->rts_ratefb_lmt = 0xF;
+
+ if (padapter->mlmeextpriv.mlmext_info.preamble_mode == PREAMBLE_SHORT)
+ ptxdesc->rts_short = 1;
+
+ /* Set RTS BW */
+ if (pattrib->ht_en)
+ ptxdesc->rts_sc = SCMapping_8723B(padapter, pattrib);
+ }
+}
+
+static void fill_txdesc_phy_8723b(struct adapter *padapter, struct pkt_attrib *pattrib, struct txdesc_8723b *ptxdesc)
+{
+ if (pattrib->ht_en) {
+ ptxdesc->data_bw = BWMapping_8723B(padapter, pattrib);
+
+ ptxdesc->data_sc = SCMapping_8723B(padapter, pattrib);
+ }
+}
+
+static void rtl8723b_fill_default_txdesc(
+ struct xmit_frame *pxmitframe, u8 *pbuf
+)
+{
+ struct adapter *padapter;
+ struct hal_com_data *pHalData;
+ struct mlme_ext_priv *pmlmeext;
+ struct mlme_ext_info *pmlmeinfo;
+ struct pkt_attrib *pattrib;
+ struct txdesc_8723b *ptxdesc;
+ s32 bmcst;
+
+ memset(pbuf, 0, TXDESC_SIZE);
+
+ padapter = pxmitframe->padapter;
+ pHalData = GET_HAL_DATA(padapter);
+ pmlmeext = &padapter->mlmeextpriv;
+ pmlmeinfo = &(pmlmeext->mlmext_info);
+
+ pattrib = &pxmitframe->attrib;
+ bmcst = IS_MCAST(pattrib->ra);
+
+ ptxdesc = (struct txdesc_8723b *)pbuf;
+
+ if (pxmitframe->frame_tag == DATA_FRAMETAG) {
+ u8 drv_userate = 0;
+
+ ptxdesc->macid = pattrib->mac_id; /* CAM_ID(MAC_ID) */
+ ptxdesc->rate_id = pattrib->raid;
+ ptxdesc->qsel = pattrib->qsel;
+ ptxdesc->seq = pattrib->seqnum;
+
+ ptxdesc->sectype = fill_txdesc_sectype(pattrib);
+ fill_txdesc_vcs_8723b(padapter, pattrib, ptxdesc);
+
+ if (pattrib->icmp_pkt == 1 && padapter->registrypriv.wifi_spec == 1)
+ drv_userate = 1;
+
+ if (
+ (pattrib->ether_type != 0x888e) &&
+ (pattrib->ether_type != 0x0806) &&
+ (pattrib->ether_type != 0x88B4) &&
+ (pattrib->dhcp_pkt != 1) &&
+ (drv_userate != 1)
+ ) {
+ /* Non EAP & ARP & DHCP type data packet */
+
+ if (pattrib->ampdu_en) {
+ ptxdesc->agg_en = 1; /* AGG EN */
+ ptxdesc->max_agg_num = 0x1f;
+ ptxdesc->ampdu_density = pattrib->ampdu_spacing;
+ } else
+ ptxdesc->bk = 1; /* AGG BK */
+
+ fill_txdesc_phy_8723b(padapter, pattrib, ptxdesc);
+
+ ptxdesc->data_ratefb_lmt = 0x1F;
+
+ if (!pHalData->fw_ractrl) {
+ ptxdesc->userate = 1;
+
+ if (pHalData->dmpriv.INIDATA_RATE[pattrib->mac_id] & BIT(7))
+ ptxdesc->data_short = 1;
+
+ ptxdesc->datarate = pHalData->dmpriv.INIDATA_RATE[pattrib->mac_id] & 0x7F;
+ }
+
+ if (padapter->fix_rate != 0xFF) { /* modify data rate by iwpriv */
+ ptxdesc->userate = 1;
+ if (padapter->fix_rate & BIT(7))
+ ptxdesc->data_short = 1;
+
+ ptxdesc->datarate = (padapter->fix_rate & 0x7F);
+ ptxdesc->disdatafb = 1;
+ }
+
+ if (pattrib->ldpc)
+ ptxdesc->data_ldpc = 1;
+ if (pattrib->stbc)
+ ptxdesc->data_stbc = 1;
+ } else {
+ /* EAP data packet and ARP packet. */
+ /* Use the 1M data rate to send the EAP/ARP packet. */
+ /* This will maybe make the handshake smooth. */
+
+ ptxdesc->bk = 1; /* AGG BK */
+ ptxdesc->userate = 1; /* driver uses rate */
+ if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT)
+ ptxdesc->data_short = 1;/* DATA_SHORT */
+ ptxdesc->datarate = MRateToHwRate(pmlmeext->tx_rate);
+ }
+
+ ptxdesc->usb_txagg_num = pxmitframe->agg_num;
+ } else if (pxmitframe->frame_tag == MGNT_FRAMETAG) {
+ ptxdesc->macid = pattrib->mac_id; /* CAM_ID(MAC_ID) */
+ ptxdesc->qsel = pattrib->qsel;
+ ptxdesc->rate_id = pattrib->raid; /* Rate ID */
+ ptxdesc->seq = pattrib->seqnum;
+ ptxdesc->userate = 1; /* driver uses rate, 1M */
+
+ ptxdesc->mbssid = pattrib->mbssid & 0xF;
+
+ ptxdesc->rty_lmt_en = 1; /* retry limit enable */
+ if (pattrib->retry_ctrl) {
+ ptxdesc->data_rt_lmt = 6;
+ } else {
+ ptxdesc->data_rt_lmt = 12;
+ }
+
+ ptxdesc->datarate = MRateToHwRate(pmlmeext->tx_rate);
+
+ /* CCX-TXRPT ack for xmit mgmt frames. */
+ if (pxmitframe->ack_report) {
+ ptxdesc->spe_rpt = 1;
+ ptxdesc->sw_define = (u8)(GET_PRIMARY_ADAPTER(padapter)->xmitpriv.seq_no);
+ }
+ } else {
+ ptxdesc->macid = pattrib->mac_id; /* CAM_ID(MAC_ID) */
+ ptxdesc->rate_id = pattrib->raid; /* Rate ID */
+ ptxdesc->qsel = pattrib->qsel;
+ ptxdesc->seq = pattrib->seqnum;
+ ptxdesc->userate = 1; /* driver uses rate */
+ ptxdesc->datarate = MRateToHwRate(pmlmeext->tx_rate);
+ }
+
+ ptxdesc->pktlen = pattrib->last_txcmdsz;
+ ptxdesc->offset = TXDESC_SIZE + OFFSET_SZ;
+
+ if (bmcst)
+ ptxdesc->bmc = 1;
+
+ /* 2009.11.05. tynli_test. Suggested by SD4 Filen for FW LPS.
+ * (1) The sequence number of each non-Qos frame / broadcast /
+ * multicast / mgnt frame should be controlled by Hw because Fw
+ * will also send null data which we cannot control when Fw LPS
+ * enable.
+ * --> default enable non-Qos data sequense number. 2010.06.23.
+ * by tynli.
+ * (2) Enable HW SEQ control for beacon packet, because we use
+ * Hw beacon.
+ * (3) Use HW Qos SEQ to control the seq num of Ext port non-Qos
+ * packets.
+ * 2010.06.23. Added by tynli.
+ */
+ if (!pattrib->qos_en) /* Hw set sequence number */
+ ptxdesc->en_hwseq = 1; /* HWSEQ_EN */
+}
+
+/* Description:
+ *
+ * Parameters:
+ * pxmitframe xmitframe
+ * pbuf where to fill tx desc
+ */
+void rtl8723b_update_txdesc(struct xmit_frame *pxmitframe, u8 *pbuf)
+{
+ struct tx_desc *pdesc;
+
+ rtl8723b_fill_default_txdesc(pxmitframe, pbuf);
+ pdesc = (struct tx_desc *)pbuf;
+ rtl8723b_cal_txdesc_chksum(pdesc);
+}
+
+/* */
+/* Description: In normal chip, we should send some packet to Hw which will be used by Fw */
+/* in FW LPS mode. The function is to fill the Tx descriptor of this packets, then */
+/* Fw can tell Hw to send these packet derectly. */
+/* Added by tynli. 2009.10.15. */
+/* */
+/* type1:pspoll, type2:null */
+void rtl8723b_fill_fake_txdesc(
+ struct adapter *padapter,
+ u8 *pDesc,
+ u32 BufferLen,
+ u8 IsPsPoll,
+ u8 IsBTQosNull,
+ u8 bDataFrame
+)
+{
+ /* Clear all status */
+ memset(pDesc, 0, TXDESC_SIZE);
+
+ SET_TX_DESC_FIRST_SEG_8723B(pDesc, 1); /* bFirstSeg; */
+ SET_TX_DESC_LAST_SEG_8723B(pDesc, 1); /* bLastSeg; */
+
+ SET_TX_DESC_OFFSET_8723B(pDesc, 0x28); /* Offset = 32 */
+
+ SET_TX_DESC_PKT_SIZE_8723B(pDesc, BufferLen); /* Buffer size + command header */
+ SET_TX_DESC_QUEUE_SEL_8723B(pDesc, QSLT_MGNT); /* Fixed queue of Mgnt queue */
+
+ /* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error vlaue by Hw. */
+ if (IsPsPoll) {
+ SET_TX_DESC_NAV_USE_HDR_8723B(pDesc, 1);
+ } else {
+ SET_TX_DESC_HWSEQ_EN_8723B(pDesc, 1); /* Hw set sequence number */
+ SET_TX_DESC_HWSEQ_SEL_8723B(pDesc, 0);
+ }
+
+ if (IsBTQosNull) {
+ SET_TX_DESC_BT_INT_8723B(pDesc, 1);
+ }
+
+ SET_TX_DESC_USE_RATE_8723B(pDesc, 1); /* use data rate which is set by Sw */
+ SET_TX_DESC_OWN_8723B((u8 *)pDesc, 1);
+
+ SET_TX_DESC_TX_RATE_8723B(pDesc, DESC8723B_RATE1M);
+
+ /* */
+ /* Encrypt the data frame if under security mode excepct null data. Suggested by CCW. */
+ /* */
+ if (bDataFrame) {
+ u32 EncAlg;
+
+ EncAlg = padapter->securitypriv.dot11PrivacyAlgrthm;
+ switch (EncAlg) {
+ case _NO_PRIVACY_:
+ SET_TX_DESC_SEC_TYPE_8723B(pDesc, 0x0);
+ break;
+ case _WEP40_:
+ case _WEP104_:
+ case _TKIP_:
+ SET_TX_DESC_SEC_TYPE_8723B(pDesc, 0x1);
+ break;
+ case _SMS4_:
+ SET_TX_DESC_SEC_TYPE_8723B(pDesc, 0x2);
+ break;
+ case _AES_:
+ SET_TX_DESC_SEC_TYPE_8723B(pDesc, 0x3);
+ break;
+ default:
+ SET_TX_DESC_SEC_TYPE_8723B(pDesc, 0x0);
+ break;
+ }
+ }
+
+ /* USB interface drop packet if the checksum of descriptor isn't correct. */
+ /* Using this checksum can let hardware recovery from packet bulk out error (e.g. Cancel URC, Bulk out error.). */
+ rtl8723b_cal_txdesc_chksum((struct tx_desc *)pDesc);
+}
+
+static void hw_var_set_opmode(struct adapter *padapter, u8 variable, u8 *val)
+{
+ u8 val8;
+ u8 mode = *((u8 *)val);
+
+ {
+ /* disable Port0 TSF update */
+ val8 = rtw_read8(padapter, REG_BCN_CTRL);
+ val8 |= DIS_TSF_UDT;
+ rtw_write8(padapter, REG_BCN_CTRL, val8);
+
+ /* set net_type */
+ Set_MSR(padapter, mode);
+
+ if ((mode == _HW_STATE_STATION_) || (mode == _HW_STATE_NOLINK_)) {
+ {
+ StopTxBeacon(padapter);
+ }
+
+ /* disable atim wnd */
+ rtw_write8(padapter, REG_BCN_CTRL, DIS_TSF_UDT|EN_BCN_FUNCTION|DIS_ATIM);
+ /* rtw_write8(padapter, REG_BCN_CTRL, 0x18); */
+ } else if (mode == _HW_STATE_ADHOC_) {
+ ResumeTxBeacon(padapter);
+ rtw_write8(padapter, REG_BCN_CTRL, DIS_TSF_UDT|EN_BCN_FUNCTION|DIS_BCNQ_SUB);
+ } else if (mode == _HW_STATE_AP_) {
+
+ ResumeTxBeacon(padapter);
+
+ rtw_write8(padapter, REG_BCN_CTRL, DIS_TSF_UDT|DIS_BCNQ_SUB);
+
+ /* Set RCR */
+ rtw_write32(padapter, REG_RCR, 0x7000208e);/* CBSSID_DATA must set to 0, reject ICV_ERR packet */
+ /* enable to rx data frame */
+ rtw_write16(padapter, REG_RXFLTMAP2, 0xFFFF);
+ /* enable to rx ps-poll */
+ rtw_write16(padapter, REG_RXFLTMAP1, 0x0400);
+
+ /* Beacon Control related register for first time */
+ rtw_write8(padapter, REG_BCNDMATIM, 0x02); /* 2ms */
+
+ /* rtw_write8(padapter, REG_BCN_MAX_ERR, 0xFF); */
+ rtw_write8(padapter, REG_ATIMWND, 0x0a); /* 10ms */
+ rtw_write16(padapter, REG_BCNTCFG, 0x00);
+ rtw_write16(padapter, REG_TBTT_PROHIBIT, 0xff04);
+ rtw_write16(padapter, REG_TSFTR_SYN_OFFSET, 0x7fff);/* +32767 (~32ms) */
+
+ /* reset TSF */
+ rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(0));
+
+ /* enable BCN0 Function for if1 */
+ /* don't enable update TSF0 for if1 (due to TSF update when beacon/probe rsp are received) */
+ rtw_write8(padapter, REG_BCN_CTRL, (DIS_TSF_UDT|EN_BCN_FUNCTION|EN_TXBCN_RPT|DIS_BCNQ_SUB));
+
+ /* SW_BCN_SEL - Port0 */
+ /* rtw_write8(Adapter, REG_DWBCN1_CTRL_8192E+2, rtw_read8(Adapter, REG_DWBCN1_CTRL_8192E+2) & ~BIT4); */
+ rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL);
+
+ /* select BCN on port 0 */
+ rtw_write8(
+ padapter,
+ REG_CCK_CHECK_8723B,
+ (rtw_read8(padapter, REG_CCK_CHECK_8723B)&~BIT_BCN_PORT_SEL)
+ );
+
+ /* dis BCN1 ATIM WND if if2 is station */
+ val8 = rtw_read8(padapter, REG_BCN_CTRL_1);
+ val8 |= DIS_ATIM;
+ rtw_write8(padapter, REG_BCN_CTRL_1, val8);
+ }
+ }
+}
+
+static void hw_var_set_macaddr(struct adapter *padapter, u8 variable, u8 *val)
+{
+ u8 idx = 0;
+ u32 reg_macid;
+
+ reg_macid = REG_MACID;
+
+ for (idx = 0 ; idx < 6; idx++)
+ rtw_write8(GET_PRIMARY_ADAPTER(padapter), (reg_macid+idx), val[idx]);
+}
+
+static void hw_var_set_bssid(struct adapter *padapter, u8 variable, u8 *val)
+{
+ u8 idx = 0;
+ u32 reg_bssid;
+
+ reg_bssid = REG_BSSID;
+
+ for (idx = 0 ; idx < 6; idx++)
+ rtw_write8(padapter, (reg_bssid+idx), val[idx]);
+}
+
+static void hw_var_set_bcn_func(struct adapter *padapter, u8 variable, u8 *val)
+{
+ u32 bcn_ctrl_reg;
+
+ bcn_ctrl_reg = REG_BCN_CTRL;
+
+ if (*(u8 *)val)
+ rtw_write8(padapter, bcn_ctrl_reg, (EN_BCN_FUNCTION | EN_TXBCN_RPT));
+ else {
+ u8 val8;
+ val8 = rtw_read8(padapter, bcn_ctrl_reg);
+ val8 &= ~(EN_BCN_FUNCTION | EN_TXBCN_RPT);
+
+ /* Always enable port0 beacon function for PSTDMA */
+ if (REG_BCN_CTRL == bcn_ctrl_reg)
+ val8 |= EN_BCN_FUNCTION;
+
+ rtw_write8(padapter, bcn_ctrl_reg, val8);
+ }
+}
+
+static void hw_var_set_correct_tsf(struct adapter *padapter, u8 variable, u8 *val)
+{
+ u8 val8;
+ u64 tsf;
+ struct mlme_ext_priv *pmlmeext;
+ struct mlme_ext_info *pmlmeinfo;
+
+
+ pmlmeext = &padapter->mlmeextpriv;
+ pmlmeinfo = &pmlmeext->mlmext_info;
+
+ tsf = pmlmeext->TSFValue-do_div(pmlmeext->TSFValue, (pmlmeinfo->bcn_interval*1024))-1024; /* us */
+
+ if (
+ ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) ||
+ ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
+ )
+ StopTxBeacon(padapter);
+
+ {
+ /* disable related TSF function */
+ val8 = rtw_read8(padapter, REG_BCN_CTRL);
+ val8 &= ~EN_BCN_FUNCTION;
+ rtw_write8(padapter, REG_BCN_CTRL, val8);
+
+ rtw_write32(padapter, REG_TSFTR, tsf);
+ rtw_write32(padapter, REG_TSFTR+4, tsf>>32);
+
+ /* enable related TSF function */
+ val8 = rtw_read8(padapter, REG_BCN_CTRL);
+ val8 |= EN_BCN_FUNCTION;
+ rtw_write8(padapter, REG_BCN_CTRL, val8);
+ }
+
+ if (
+ ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) ||
+ ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
+ )
+ ResumeTxBeacon(padapter);
+}
+
+static void hw_var_set_mlme_disconnect(struct adapter *padapter, u8 variable, u8 *val)
+{
+ u8 val8;
+
+ /* Set RCR to not to receive data frame when NO LINK state */
+ /* rtw_write32(padapter, REG_RCR, rtw_read32(padapter, REG_RCR) & ~RCR_ADF); */
+ /* reject all data frames */
+ rtw_write16(padapter, REG_RXFLTMAP2, 0);
+
+ /* reset TSF */
+ rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(0));
+
+ /* disable update TSF */
+ val8 = rtw_read8(padapter, REG_BCN_CTRL);
+ val8 |= DIS_TSF_UDT;
+ rtw_write8(padapter, REG_BCN_CTRL, val8);
+}
+
+static void hw_var_set_mlme_sitesurvey(struct adapter *padapter, u8 variable, u8 *val)
+{
+ u32 value_rcr, rcr_clear_bit, reg_bcn_ctl;
+ u16 value_rxfltmap2;
+ u8 val8;
+ struct hal_com_data *pHalData;
+ struct mlme_priv *pmlmepriv;
+
+
+ pHalData = GET_HAL_DATA(padapter);
+ pmlmepriv = &padapter->mlmepriv;
+
+ reg_bcn_ctl = REG_BCN_CTRL;
+
+ rcr_clear_bit = RCR_CBSSID_BCN;
+
+ /* config RCR to receive different BSSID & not to receive data frame */
+ value_rxfltmap2 = 0;
+
+ if ((check_fwstate(pmlmepriv, WIFI_AP_STATE) == true))
+ rcr_clear_bit = RCR_CBSSID_BCN;
+
+ value_rcr = rtw_read32(padapter, REG_RCR);
+
+ if (*((u8 *)val)) {
+ /* under sitesurvey */
+ value_rcr &= ~(rcr_clear_bit);
+ rtw_write32(padapter, REG_RCR, value_rcr);
+
+ rtw_write16(padapter, REG_RXFLTMAP2, value_rxfltmap2);
+
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) {
+ /* disable update TSF */
+ val8 = rtw_read8(padapter, reg_bcn_ctl);
+ val8 |= DIS_TSF_UDT;
+ rtw_write8(padapter, reg_bcn_ctl, val8);
+ }
+
+ /* Save original RRSR setting. */
+ pHalData->RegRRSR = rtw_read16(padapter, REG_RRSR);
+ } else {
+ /* sitesurvey done */
+ if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)))
+ /* enable to rx data frame */
+ rtw_write16(padapter, REG_RXFLTMAP2, 0xFFFF);
+
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) {
+ /* enable update TSF */
+ val8 = rtw_read8(padapter, reg_bcn_ctl);
+ val8 &= ~DIS_TSF_UDT;
+ rtw_write8(padapter, reg_bcn_ctl, val8);
+ }
+
+ value_rcr |= rcr_clear_bit;
+ rtw_write32(padapter, REG_RCR, value_rcr);
+
+ /* Restore original RRSR setting. */
+ rtw_write16(padapter, REG_RRSR, pHalData->RegRRSR);
+ }
+}
+
+static void hw_var_set_mlme_join(struct adapter *padapter, u8 variable, u8 *val)
+{
+ u8 val8;
+ u16 val16;
+ u32 val32;
+ u8 RetryLimit;
+ u8 type;
+ struct mlme_priv *pmlmepriv;
+ struct eeprom_priv *pEEPROM;
+
+
+ RetryLimit = 0x30;
+ type = *(u8 *)val;
+ pmlmepriv = &padapter->mlmepriv;
+ pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
+
+ if (type == 0) { /* prepare to join */
+ /* enable to rx data frame.Accept all data frame */
+ /* rtw_write32(padapter, REG_RCR, rtw_read32(padapter, REG_RCR)|RCR_ADF); */
+ rtw_write16(padapter, REG_RXFLTMAP2, 0xFFFF);
+
+ val32 = rtw_read32(padapter, REG_RCR);
+ if (padapter->in_cta_test)
+ val32 &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);/* RCR_ADF */
+ else
+ val32 |= RCR_CBSSID_DATA|RCR_CBSSID_BCN;
+ rtw_write32(padapter, REG_RCR, val32);
+
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
+ RetryLimit = (pEEPROM->CustomerID == RT_CID_CCX) ? 7 : 48;
+ else /* Ad-hoc Mode */
+ RetryLimit = 0x7;
+ } else if (type == 1) /* joinbss_event call back when join res < 0 */
+ rtw_write16(padapter, REG_RXFLTMAP2, 0x00);
+ else if (type == 2) { /* sta add event call back */
+ /* enable update TSF */
+ val8 = rtw_read8(padapter, REG_BCN_CTRL);
+ val8 &= ~DIS_TSF_UDT;
+ rtw_write8(padapter, REG_BCN_CTRL, val8);
+
+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE))
+ RetryLimit = 0x7;
+ }
+
+ val16 = (RetryLimit << RETRY_LIMIT_SHORT_SHIFT) | (RetryLimit << RETRY_LIMIT_LONG_SHIFT);
+ rtw_write16(padapter, REG_RL, val16);
+}
+
+void CCX_FwC2HTxRpt_8723b(struct adapter *padapter, u8 *pdata, u8 len)
+{
+
+#define GET_8723B_C2H_TX_RPT_LIFE_TIME_OVER(_Header) LE_BITS_TO_1BYTE((_Header + 0), 6, 1)
+#define GET_8723B_C2H_TX_RPT_RETRY_OVER(_Header) LE_BITS_TO_1BYTE((_Header + 0), 7, 1)
+
+ if (GET_8723B_C2H_TX_RPT_RETRY_OVER(pdata) | GET_8723B_C2H_TX_RPT_LIFE_TIME_OVER(pdata)) {
+ rtw_ack_tx_done(&padapter->xmitpriv, RTW_SCTX_DONE_CCX_PKT_FAIL);
+ }
+/*
+ else if (seq_no != padapter->xmitpriv.seq_no) {
+ rtw_ack_tx_done(&padapter->xmitpriv, RTW_SCTX_DONE_CCX_PKT_FAIL);
+ }
+*/
+ else
+ rtw_ack_tx_done(&padapter->xmitpriv, RTW_SCTX_DONE_SUCCESS);
+}
+
+s32 c2h_id_filter_ccx_8723b(u8 *buf)
+{
+ struct c2h_evt_hdr_88xx *c2h_evt = (struct c2h_evt_hdr_88xx *)buf;
+ s32 ret = false;
+ if (c2h_evt->id == C2H_CCX_TX_RPT)
+ ret = true;
+
+ return ret;
+}
+
+
+s32 c2h_handler_8723b(struct adapter *padapter, u8 *buf)
+{
+ struct c2h_evt_hdr_88xx *pC2hEvent = (struct c2h_evt_hdr_88xx *)buf;
+ s32 ret = _SUCCESS;
+
+ if (!pC2hEvent) {
+ ret = _FAIL;
+ goto exit;
+ }
+
+ switch (pC2hEvent->id) {
+ case C2H_AP_RPT_RSP:
+ break;
+ case C2H_DBG:
+ {
+ }
+ break;
+
+ case C2H_CCX_TX_RPT:
+/* CCX_FwC2HTxRpt(padapter, QueueID, pC2hEvent->payload); */
+ break;
+
+ case C2H_EXT_RA_RPT:
+/* C2HExtRaRptHandler(padapter, pC2hEvent->payload, C2hEvent.CmdLen); */
+ break;
+
+ case C2H_HW_INFO_EXCH:
+ break;
+
+ case C2H_8723B_BT_INFO:
+ hal_btcoex_BtInfoNotify(padapter, pC2hEvent->plen, pC2hEvent->payload);
+ break;
+
+ default:
+ break;
+ }
+
+ /* Clear event to notify FW we have read the command. */
+ /* Note: */
+ /* If this field isn't clear, the FW won't update the next command message. */
+/* rtw_write8(padapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE); */
+exit:
+ return ret;
+}
+
+static void process_c2h_event(struct adapter *padapter, struct c2h_evt_hdr_t *pC2hEvent, u8 *c2hBuf)
+{
+ if (!c2hBuf)
+ return;
+
+ switch (pC2hEvent->CmdID) {
+ case C2H_AP_RPT_RSP:
+ break;
+ case C2H_DBG:
+ {
+ }
+ break;
+
+ case C2H_CCX_TX_RPT:
+/* CCX_FwC2HTxRpt(padapter, QueueID, tmpBuf); */
+ break;
+
+ case C2H_EXT_RA_RPT:
+/* C2HExtRaRptHandler(padapter, tmpBuf, C2hEvent.CmdLen); */
+ break;
+
+ case C2H_HW_INFO_EXCH:
+ break;
+
+ case C2H_8723B_BT_INFO:
+ hal_btcoex_BtInfoNotify(padapter, pC2hEvent->CmdLen, c2hBuf);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void C2HPacketHandler_8723B(struct adapter *padapter, u8 *pbuffer, u16 length)
+{
+ struct c2h_evt_hdr_t C2hEvent;
+ u8 *tmpBuf = NULL;
+ C2hEvent.CmdID = pbuffer[0];
+ C2hEvent.CmdSeq = pbuffer[1];
+ C2hEvent.CmdLen = length-2;
+ tmpBuf = pbuffer+2;
+
+ process_c2h_event(padapter, &C2hEvent, tmpBuf);
+ /* c2h_handler_8723b(padapter,&C2hEvent); */
+}
+
+void SetHwReg8723B(struct adapter *padapter, u8 variable, u8 *val)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ u8 val8;
+ u32 val32;
+
+ switch (variable) {
+ case HW_VAR_MEDIA_STATUS:
+ val8 = rtw_read8(padapter, MSR) & 0x0c;
+ val8 |= *val;
+ rtw_write8(padapter, MSR, val8);
+ break;
+
+ case HW_VAR_MEDIA_STATUS1:
+ val8 = rtw_read8(padapter, MSR) & 0x03;
+ val8 |= *val << 2;
+ rtw_write8(padapter, MSR, val8);
+ break;
+
+ case HW_VAR_SET_OPMODE:
+ hw_var_set_opmode(padapter, variable, val);
+ break;
+
+ case HW_VAR_MAC_ADDR:
+ hw_var_set_macaddr(padapter, variable, val);
+ break;
+
+ case HW_VAR_BSSID:
+ hw_var_set_bssid(padapter, variable, val);
+ break;
+
+ case HW_VAR_BASIC_RATE:
+ {
+ struct mlme_ext_info *mlmext_info = &padapter->mlmeextpriv.mlmext_info;
+ u16 BrateCfg = 0;
+ u16 rrsr_2g_force_mask = (RRSR_11M|RRSR_5_5M|RRSR_1M);
+ u16 rrsr_2g_allow_mask = (RRSR_24M|RRSR_12M|RRSR_6M|RRSR_CCK_RATES);
+
+ HalSetBrateCfg(padapter, val, &BrateCfg);
+
+ /* apply force and allow mask */
+ BrateCfg |= rrsr_2g_force_mask;
+ BrateCfg &= rrsr_2g_allow_mask;
+
+ /* IOT consideration */
+ if (mlmext_info->assoc_AP_vendor == HT_IOT_PEER_CISCO) {
+ /* if peer is cisco and didn't use ofdm rate, we enable 6M ack */
+ if ((BrateCfg & (RRSR_24M|RRSR_12M|RRSR_6M)) == 0)
+ BrateCfg |= RRSR_6M;
+ }
+
+ pHalData->BasicRateSet = BrateCfg;
+
+ /* Set RRSR rate table. */
+ rtw_write16(padapter, REG_RRSR, BrateCfg);
+ rtw_write8(padapter, REG_RRSR+2, rtw_read8(padapter, REG_RRSR+2)&0xf0);
+ }
+ break;
+
+ case HW_VAR_TXPAUSE:
+ rtw_write8(padapter, REG_TXPAUSE, *val);
+ break;
+
+ case HW_VAR_BCN_FUNC:
+ hw_var_set_bcn_func(padapter, variable, val);
+ break;
+
+ case HW_VAR_CORRECT_TSF:
+ hw_var_set_correct_tsf(padapter, variable, val);
+ break;
+
+ case HW_VAR_CHECK_BSSID:
+ {
+ u32 val32;
+ val32 = rtw_read32(padapter, REG_RCR);
+ if (*val)
+ val32 |= RCR_CBSSID_DATA|RCR_CBSSID_BCN;
+ else
+ val32 &= ~(RCR_CBSSID_DATA|RCR_CBSSID_BCN);
+ rtw_write32(padapter, REG_RCR, val32);
+ }
+ break;
+
+ case HW_VAR_MLME_DISCONNECT:
+ hw_var_set_mlme_disconnect(padapter, variable, val);
+ break;
+
+ case HW_VAR_MLME_SITESURVEY:
+ hw_var_set_mlme_sitesurvey(padapter, variable, val);
+
+ hal_btcoex_ScanNotify(padapter, *val?true:false);
+ break;
+
+ case HW_VAR_MLME_JOIN:
+ hw_var_set_mlme_join(padapter, variable, val);
+
+ switch (*val) {
+ case 0:
+ /* prepare to join */
+ hal_btcoex_ConnectNotify(padapter, true);
+ break;
+ case 1:
+ /* joinbss_event callback when join res < 0 */
+ hal_btcoex_ConnectNotify(padapter, false);
+ break;
+ case 2:
+ /* sta add event callback */
+/* rtw_btcoex_MediaStatusNotify(padapter, RT_MEDIA_CONNECT); */
+ break;
+ }
+ break;
+
+ case HW_VAR_ON_RCR_AM:
+ val32 = rtw_read32(padapter, REG_RCR);
+ val32 |= RCR_AM;
+ rtw_write32(padapter, REG_RCR, val32);
+ break;
+
+ case HW_VAR_OFF_RCR_AM:
+ val32 = rtw_read32(padapter, REG_RCR);
+ val32 &= ~RCR_AM;
+ rtw_write32(padapter, REG_RCR, val32);
+ break;
+
+ case HW_VAR_BEACON_INTERVAL:
+ rtw_write16(padapter, REG_BCN_INTERVAL, *((u16 *)val));
+ break;
+
+ case HW_VAR_SLOT_TIME:
+ rtw_write8(padapter, REG_SLOT, *val);
+ break;
+
+ case HW_VAR_RESP_SIFS:
+ /* SIFS_Timer = 0x0a0a0808; */
+ /* RESP_SIFS for CCK */
+ rtw_write8(padapter, REG_RESP_SIFS_CCK, val[0]); /* SIFS_T2T_CCK (0x08) */
+ rtw_write8(padapter, REG_RESP_SIFS_CCK+1, val[1]); /* SIFS_R2T_CCK(0x08) */
+ /* RESP_SIFS for OFDM */
+ rtw_write8(padapter, REG_RESP_SIFS_OFDM, val[2]); /* SIFS_T2T_OFDM (0x0a) */
+ rtw_write8(padapter, REG_RESP_SIFS_OFDM+1, val[3]); /* SIFS_R2T_OFDM(0x0a) */
+ break;
+
+ case HW_VAR_ACK_PREAMBLE:
+ {
+ u8 regTmp;
+ u8 bShortPreamble = *val;
+
+ /* Joseph marked out for Netgear 3500 TKIP channel 7 issue.(Temporarily) */
+ /* regTmp = (pHalData->nCur40MhzPrimeSC)<<5; */
+ regTmp = 0;
+ if (bShortPreamble)
+ regTmp |= 0x80;
+ rtw_write8(padapter, REG_RRSR+2, regTmp);
+ }
+ break;
+
+ case HW_VAR_CAM_EMPTY_ENTRY:
+ {
+ u8 ucIndex = *val;
+ u8 i;
+ u32 ulCommand = 0;
+ u32 ulContent = 0;
+ u32 ulEncAlgo = CAM_AES;
+
+ for (i = 0; i < CAM_CONTENT_COUNT; i++) {
+ /* filled id in CAM config 2 byte */
+ if (i == 0) {
+ ulContent |= (ucIndex & 0x03) | ((u16)(ulEncAlgo)<<2);
+ /* ulContent |= CAM_VALID; */
+ } else
+ ulContent = 0;
+
+ /* polling bit, and No Write enable, and address */
+ ulCommand = CAM_CONTENT_COUNT*ucIndex+i;
+ ulCommand = ulCommand | CAM_POLLINIG | CAM_WRITE;
+ /* write content 0 is equall to mark invalid */
+ rtw_write32(padapter, WCAMI, ulContent); /* mdelay(40); */
+ rtw_write32(padapter, RWCAM, ulCommand); /* mdelay(40); */
+ }
+ }
+ break;
+
+ case HW_VAR_CAM_INVALID_ALL:
+ rtw_write32(padapter, RWCAM, BIT(31)|BIT(30));
+ break;
+
+ case HW_VAR_CAM_WRITE:
+ {
+ u32 cmd;
+ u32 *cam_val = (u32 *)val;
+
+ rtw_write32(padapter, WCAMI, cam_val[0]);
+
+ cmd = CAM_POLLINIG | CAM_WRITE | cam_val[1];
+ rtw_write32(padapter, RWCAM, cmd);
+ }
+ break;
+
+ case HW_VAR_AC_PARAM_VO:
+ rtw_write32(padapter, REG_EDCA_VO_PARAM, *((u32 *)val));
+ break;
+
+ case HW_VAR_AC_PARAM_VI:
+ rtw_write32(padapter, REG_EDCA_VI_PARAM, *((u32 *)val));
+ break;
+
+ case HW_VAR_AC_PARAM_BE:
+ pHalData->AcParam_BE = ((u32 *)(val))[0];
+ rtw_write32(padapter, REG_EDCA_BE_PARAM, *((u32 *)val));
+ break;
+
+ case HW_VAR_AC_PARAM_BK:
+ rtw_write32(padapter, REG_EDCA_BK_PARAM, *((u32 *)val));
+ break;
+
+ case HW_VAR_ACM_CTRL:
+ {
+ u8 ctrl = *((u8 *)val);
+ u8 hwctrl = 0;
+
+ if (ctrl != 0) {
+ hwctrl |= AcmHw_HwEn;
+
+ if (ctrl & BIT(1)) /* BE */
+ hwctrl |= AcmHw_BeqEn;
+
+ if (ctrl & BIT(2)) /* VI */
+ hwctrl |= AcmHw_ViqEn;
+
+ if (ctrl & BIT(3)) /* VO */
+ hwctrl |= AcmHw_VoqEn;
+ }
+
+ rtw_write8(padapter, REG_ACMHWCTRL, hwctrl);
+ }
+ break;
+
+ case HW_VAR_AMPDU_FACTOR:
+ {
+ u32 AMPDULen = (*((u8 *)val));
+
+ if (AMPDULen < HT_AGG_SIZE_32K)
+ AMPDULen = (0x2000 << (*((u8 *)val)))-1;
+ else
+ AMPDULen = 0x7fff;
+
+ rtw_write32(padapter, REG_AMPDU_MAX_LENGTH_8723B, AMPDULen);
+ }
+ break;
+
+ case HW_VAR_H2C_FW_PWRMODE:
+ {
+ u8 psmode = *val;
+
+ /* Forece leave RF low power mode for 1T1R to prevent conficting setting in Fw power */
+ /* saving sequence. 2010.06.07. Added by tynli. Suggested by SD3 yschang. */
+ if (psmode != PS_MODE_ACTIVE) {
+ ODM_RF_Saving(&pHalData->odmpriv, true);
+ }
+
+ /* if (psmode != PS_MODE_ACTIVE) { */
+ /* rtl8723b_set_lowpwr_lps_cmd(padapter, true); */
+ /* else { */
+ /* rtl8723b_set_lowpwr_lps_cmd(padapter, false); */
+ /* */
+ rtl8723b_set_FwPwrMode_cmd(padapter, psmode);
+ }
+ break;
+ case HW_VAR_H2C_PS_TUNE_PARAM:
+ rtl8723b_set_FwPsTuneParam_cmd(padapter);
+ break;
+
+ case HW_VAR_H2C_FW_JOINBSSRPT:
+ rtl8723b_set_FwJoinBssRpt_cmd(padapter, *val);
+ break;
+
+ case HW_VAR_INITIAL_GAIN:
+ {
+ struct dig_t *pDigTable = &pHalData->odmpriv.DM_DigTable;
+ u32 rx_gain = *(u32 *)val;
+
+ if (rx_gain == 0xff) {/* restore rx gain */
+ ODM_Write_DIG(&pHalData->odmpriv, pDigTable->BackupIGValue);
+ } else {
+ pDigTable->BackupIGValue = pDigTable->CurIGValue;
+ ODM_Write_DIG(&pHalData->odmpriv, rx_gain);
+ }
+ }
+ break;
+
+ case HW_VAR_EFUSE_USAGE:
+ pHalData->EfuseUsedPercentage = *val;
+ break;
+
+ case HW_VAR_EFUSE_BYTES:
+ pHalData->EfuseUsedBytes = *((u16 *)val);
+ break;
+
+ case HW_VAR_EFUSE_BT_USAGE:
+#ifdef HAL_EFUSE_MEMORY
+ pHalData->EfuseHal.BTEfuseUsedPercentage = *val;
+#endif
+ break;
+
+ case HW_VAR_EFUSE_BT_BYTES:
+#ifdef HAL_EFUSE_MEMORY
+ pHalData->EfuseHal.BTEfuseUsedBytes = *((u16 *)val);
+#else
+ BTEfuseUsedBytes = *((u16 *)val);
+#endif
+ break;
+
+ case HW_VAR_FIFO_CLEARN_UP:
+ {
+ #define RW_RELEASE_EN BIT(18)
+ #define RXDMA_IDLE BIT(17)
+
+ struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+ u8 trycnt = 100;
+
+ /* pause tx */
+ rtw_write8(padapter, REG_TXPAUSE, 0xff);
+
+ /* keep sn */
+ padapter->xmitpriv.nqos_ssn = rtw_read16(padapter, REG_NQOS_SEQ);
+
+ if (!pwrpriv->bkeepfwalive) {
+ /* RX DMA stop */
+ val32 = rtw_read32(padapter, REG_RXPKT_NUM);
+ val32 |= RW_RELEASE_EN;
+ rtw_write32(padapter, REG_RXPKT_NUM, val32);
+ do {
+ val32 = rtw_read32(padapter, REG_RXPKT_NUM);
+ val32 &= RXDMA_IDLE;
+ if (val32)
+ break;
+ } while (--trycnt);
+
+ /* RQPN Load 0 */
+ rtw_write16(padapter, REG_RQPN_NPQ, 0);
+ rtw_write32(padapter, REG_RQPN, 0x80000000);
+ mdelay(2);
+ }
+ }
+ break;
+
+ case HW_VAR_APFM_ON_MAC:
+ pHalData->bMacPwrCtrlOn = *val;
+ break;
+
+ case HW_VAR_NAV_UPPER:
+ {
+ u32 usNavUpper = *((u32 *)val);
+
+ if (usNavUpper > HAL_NAV_UPPER_UNIT_8723B * 0xFF)
+ break;
+
+ usNavUpper = DIV_ROUND_UP(usNavUpper,
+ HAL_NAV_UPPER_UNIT_8723B);
+ rtw_write8(padapter, REG_NAV_UPPER, (u8)usNavUpper);
+ }
+ break;
+
+ case HW_VAR_H2C_MEDIA_STATUS_RPT:
+ {
+ u16 mstatus_rpt = (*(u16 *)val);
+ u8 mstatus, macId;
+
+ mstatus = (u8) (mstatus_rpt & 0xFF);
+ macId = (u8)(mstatus_rpt >> 8);
+ rtl8723b_set_FwMediaStatusRpt_cmd(padapter, mstatus, macId);
+ }
+ break;
+ case HW_VAR_BCN_VALID:
+ {
+ /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2, write 1 to clear, Clear by sw */
+ val8 = rtw_read8(padapter, REG_TDECTRL+2);
+ val8 |= BIT(0);
+ rtw_write8(padapter, REG_TDECTRL+2, val8);
+ }
+ break;
+
+ case HW_VAR_DL_BCN_SEL:
+ {
+ /* SW_BCN_SEL - Port0 */
+ val8 = rtw_read8(padapter, REG_DWBCN1_CTRL_8723B+2);
+ val8 &= ~BIT(4);
+ rtw_write8(padapter, REG_DWBCN1_CTRL_8723B+2, val8);
+ }
+ break;
+
+ case HW_VAR_DO_IQK:
+ pHalData->bNeedIQK = true;
+ break;
+
+ case HW_VAR_DL_RSVD_PAGE:
+ if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true)
+ rtl8723b_download_BTCoex_AP_mode_rsvd_page(padapter);
+ else
+ rtl8723b_download_rsvd_page(padapter, RT_MEDIA_CONNECT);
+ break;
+
+ case HW_VAR_MACID_SLEEP:
+ /* Input is MACID */
+ val32 = *(u32 *)val;
+ if (val32 > 31)
+ break;
+
+ val8 = (u8)val32; /* macid is between 0~31 */
+
+ val32 = rtw_read32(padapter, REG_MACID_SLEEP);
+ if (val32 & BIT(val8))
+ break;
+ val32 |= BIT(val8);
+ rtw_write32(padapter, REG_MACID_SLEEP, val32);
+ break;
+
+ case HW_VAR_MACID_WAKEUP:
+ /* Input is MACID */
+ val32 = *(u32 *)val;
+ if (val32 > 31)
+ break;
+
+ val8 = (u8)val32; /* macid is between 0~31 */
+
+ val32 = rtw_read32(padapter, REG_MACID_SLEEP);
+ if (!(val32 & BIT(val8)))
+ break;
+ val32 &= ~BIT(val8);
+ rtw_write32(padapter, REG_MACID_SLEEP, val32);
+ break;
+
+ default:
+ SetHwReg(padapter, variable, val);
+ break;
+ }
+}
+
+void GetHwReg8723B(struct adapter *padapter, u8 variable, u8 *val)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ u8 val8;
+ u16 val16;
+
+ switch (variable) {
+ case HW_VAR_TXPAUSE:
+ *val = rtw_read8(padapter, REG_TXPAUSE);
+ break;
+
+ case HW_VAR_BCN_VALID:
+ {
+ /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2 */
+ val8 = rtw_read8(padapter, REG_TDECTRL+2);
+ *val = (BIT(0) & val8) ? true : false;
+ }
+ break;
+
+ case HW_VAR_FWLPS_RF_ON:
+ {
+ /* When we halt NIC, we should check if FW LPS is leave. */
+ u32 valRCR;
+
+ if (
+ padapter->bSurpriseRemoved ||
+ (adapter_to_pwrctl(padapter)->rf_pwrstate == rf_off)
+ ) {
+ /* If it is in HW/SW Radio OFF or IPS state, we do not check Fw LPS Leave, */
+ /* because Fw is unload. */
+ *val = true;
+ } else {
+ valRCR = rtw_read32(padapter, REG_RCR);
+ valRCR &= 0x00070000;
+ if (valRCR)
+ *val = false;
+ else
+ *val = true;
+ }
+ }
+ break;
+
+ case HW_VAR_EFUSE_USAGE:
+ *val = pHalData->EfuseUsedPercentage;
+ break;
+
+ case HW_VAR_EFUSE_BYTES:
+ *((u16 *)val) = pHalData->EfuseUsedBytes;
+ break;
+
+ case HW_VAR_EFUSE_BT_USAGE:
+#ifdef HAL_EFUSE_MEMORY
+ *val = pHalData->EfuseHal.BTEfuseUsedPercentage;
+#endif
+ break;
+
+ case HW_VAR_EFUSE_BT_BYTES:
+#ifdef HAL_EFUSE_MEMORY
+ *((u16 *)val) = pHalData->EfuseHal.BTEfuseUsedBytes;
+#else
+ *((u16 *)val) = BTEfuseUsedBytes;
+#endif
+ break;
+
+ case HW_VAR_APFM_ON_MAC:
+ *val = pHalData->bMacPwrCtrlOn;
+ break;
+ case HW_VAR_CHK_HI_QUEUE_EMPTY:
+ val16 = rtw_read16(padapter, REG_TXPKT_EMPTY);
+ *val = (val16 & BIT(10)) ? true:false;
+ break;
+ default:
+ GetHwReg(padapter, variable, val);
+ break;
+ }
+}
+
+/* Description:
+ * Change default setting of specified variable.
+ */
+u8 SetHalDefVar8723B(struct adapter *padapter, enum hal_def_variable variable, void *pval)
+{
+ u8 bResult;
+
+ bResult = _SUCCESS;
+
+ switch (variable) {
+ default:
+ bResult = SetHalDefVar(padapter, variable, pval);
+ break;
+ }
+
+ return bResult;
+}
+
+/* Description:
+ * Query setting of specified variable.
+ */
+u8 GetHalDefVar8723B(struct adapter *padapter, enum hal_def_variable variable, void *pval)
+{
+ u8 bResult;
+
+ bResult = _SUCCESS;
+
+ switch (variable) {
+ case HAL_DEF_MAX_RECVBUF_SZ:
+ *((u32 *)pval) = MAX_RECVBUF_SZ;
+ break;
+
+ case HAL_DEF_RX_PACKET_OFFSET:
+ *((u32 *)pval) = RXDESC_SIZE + DRVINFO_SZ*8;
+ break;
+
+ case HW_VAR_MAX_RX_AMPDU_FACTOR:
+ /* Stanley@BB.SD3 suggests 16K can get stable performance */
+ /* The experiment was done on SDIO interface */
+ /* coding by Lucas@20130730 */
+ *(u32 *)pval = IEEE80211_HT_MAX_AMPDU_16K;
+ break;
+ case HAL_DEF_TX_LDPC:
+ case HAL_DEF_RX_LDPC:
+ *((u8 *)pval) = false;
+ break;
+ case HAL_DEF_TX_STBC:
+ *((u8 *)pval) = 0;
+ break;
+ case HAL_DEF_RX_STBC:
+ *((u8 *)pval) = 1;
+ break;
+ case HAL_DEF_EXPLICIT_BEAMFORMER:
+ case HAL_DEF_EXPLICIT_BEAMFORMEE:
+ *((u8 *)pval) = false;
+ break;
+
+ case HW_DEF_RA_INFO_DUMP:
+ {
+ u8 mac_id = *(u8 *)pval;
+ u32 cmd;
+
+ cmd = 0x40000100 | mac_id;
+ rtw_write32(padapter, REG_HMEBOX_DBG_2_8723B, cmd);
+ msleep(10);
+ rtw_read32(padapter, 0x2F0); // info 1
+
+ cmd = 0x40000400 | mac_id;
+ rtw_write32(padapter, REG_HMEBOX_DBG_2_8723B, cmd);
+ msleep(10);
+ rtw_read32(padapter, 0x2F0); // info 1
+ rtw_read32(padapter, 0x2F4); // info 2
+ rtw_read32(padapter, 0x2F8); // rate mask 1
+ rtw_read32(padapter, 0x2FC); // rate mask 2
+ }
+ break;
+
+ case HAL_DEF_TX_PAGE_BOUNDARY:
+ if (!padapter->registrypriv.wifi_spec) {
+ *(u8 *)pval = TX_PAGE_BOUNDARY_8723B;
+ } else {
+ *(u8 *)pval = WMM_NORMAL_TX_PAGE_BOUNDARY_8723B;
+ }
+ break;
+
+ case HAL_DEF_MACID_SLEEP:
+ *(u8 *)pval = true; /* support macid sleep */
+ break;
+
+ default:
+ bResult = GetHalDefVar(padapter, variable, pval);
+ break;
+ }
+
+ return bResult;
+}
+
+void rtl8723b_start_thread(struct adapter *padapter)
+{
+ struct xmit_priv *xmitpriv = &padapter->xmitpriv;
+
+ xmitpriv->SdioXmitThread = kthread_run(rtl8723bs_xmit_thread, padapter, "RTWHALXT");
+}
+
+void rtl8723b_stop_thread(struct adapter *padapter)
+{
+ struct xmit_priv *xmitpriv = &padapter->xmitpriv;
+
+ /* stop xmit_buf_thread */
+ if (xmitpriv->SdioXmitThread) {
+ complete(&xmitpriv->SdioXmitStart);
+ wait_for_completion(&xmitpriv->SdioXmitTerminate);
+ xmitpriv->SdioXmitThread = NULL;
+ }
+}
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c
new file mode 100644
index 000000000..a3bff27af
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c
@@ -0,0 +1,794 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include <drv_types.h>
+#include <rtw_debug.h>
+#include <rtl8723b_hal.h>
+
+/**
+ * phy_CalculateBitShift - Get shifted position of the BitMask.
+ * @BitMask: Bitmask.
+ *
+ * Return: Return the shift bit position of the mask
+ */
+static u32 phy_CalculateBitShift(u32 BitMask)
+{
+ u32 i;
+
+ for (i = 0; i <= 31; i++) {
+ if (((BitMask>>i) & 0x1) == 1)
+ break;
+ }
+ return i;
+}
+
+
+/**
+ * PHY_QueryBBReg_8723B - Read "specific bits" from BB register.
+ * @Adapter:
+ * @RegAddr: The target address to be readback
+ * @BitMask: The target bit position in the target address
+ * to be readback
+ *
+ * Return: The readback register value
+ *
+ * .. Note:: This function is equal to "GetRegSetting" in PHY programming
+ * guide
+ */
+u32 PHY_QueryBBReg_8723B(struct adapter *Adapter, u32 RegAddr, u32 BitMask)
+{
+ u32 OriginalValue, BitShift;
+
+ OriginalValue = rtw_read32(Adapter, RegAddr);
+ BitShift = phy_CalculateBitShift(BitMask);
+
+ return (OriginalValue & BitMask) >> BitShift;
+
+}
+
+
+/**
+ * PHY_SetBBReg_8723B - Write "Specific bits" to BB register (page 8~).
+ * @Adapter:
+ * @RegAddr: The target address to be modified
+ * @BitMask: The target bit position in the target address
+ * to be modified
+ * @Data: The new register value in the target bit position
+ * of the target address
+ *
+ * .. Note:: This function is equal to "PutRegSetting" in PHY programming
+ * guide
+ */
+
+void PHY_SetBBReg_8723B(
+ struct adapter *Adapter,
+ u32 RegAddr,
+ u32 BitMask,
+ u32 Data
+)
+{
+ /* u16 BBWaitCounter = 0; */
+ u32 OriginalValue, BitShift;
+
+ if (BitMask != bMaskDWord) { /* if not "double word" write */
+ OriginalValue = rtw_read32(Adapter, RegAddr);
+ BitShift = phy_CalculateBitShift(BitMask);
+ Data = ((OriginalValue & (~BitMask)) | ((Data << BitShift) & BitMask));
+ }
+
+ rtw_write32(Adapter, RegAddr, Data);
+
+}
+
+
+/* */
+/* 2. RF register R/W API */
+/* */
+
+static u32 phy_RFSerialRead_8723B(
+ struct adapter *Adapter, enum rf_path eRFPath, u32 Offset
+)
+{
+ u32 retValue = 0;
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+ struct bb_register_def *pPhyReg = &pHalData->PHYRegDef[eRFPath];
+ u32 NewOffset;
+ u32 tmplong2;
+ u8 RfPiEnable = 0;
+ u32 MaskforPhySet = 0;
+ int i = 0;
+
+ /* */
+ /* Make sure RF register offset is correct */
+ /* */
+ Offset &= 0xff;
+
+ NewOffset = Offset;
+
+ if (eRFPath == RF_PATH_A) {
+ tmplong2 = PHY_QueryBBReg(Adapter, rFPGA0_XA_HSSIParameter2|MaskforPhySet, bMaskDWord);
+ tmplong2 = (tmplong2 & (~bLSSIReadAddress)) | (NewOffset<<23) | bLSSIReadEdge; /* T65 RF */
+ PHY_SetBBReg(Adapter, rFPGA0_XA_HSSIParameter2|MaskforPhySet, bMaskDWord, tmplong2&(~bLSSIReadEdge));
+ } else {
+ tmplong2 = PHY_QueryBBReg(Adapter, rFPGA0_XB_HSSIParameter2|MaskforPhySet, bMaskDWord);
+ tmplong2 = (tmplong2 & (~bLSSIReadAddress)) | (NewOffset<<23) | bLSSIReadEdge; /* T65 RF */
+ PHY_SetBBReg(Adapter, rFPGA0_XB_HSSIParameter2|MaskforPhySet, bMaskDWord, tmplong2&(~bLSSIReadEdge));
+ }
+
+ tmplong2 = PHY_QueryBBReg(Adapter, rFPGA0_XA_HSSIParameter2|MaskforPhySet, bMaskDWord);
+ PHY_SetBBReg(Adapter, rFPGA0_XA_HSSIParameter2|MaskforPhySet, bMaskDWord, tmplong2 & (~bLSSIReadEdge));
+ PHY_SetBBReg(Adapter, rFPGA0_XA_HSSIParameter2|MaskforPhySet, bMaskDWord, tmplong2 | bLSSIReadEdge);
+
+ udelay(10);
+
+ for (i = 0; i < 2; i++)
+ udelay(MAX_STALL_TIME);
+ udelay(10);
+
+ if (eRFPath == RF_PATH_A)
+ RfPiEnable = (u8)PHY_QueryBBReg(Adapter, rFPGA0_XA_HSSIParameter1|MaskforPhySet, BIT8);
+ else if (eRFPath == RF_PATH_B)
+ RfPiEnable = (u8)PHY_QueryBBReg(Adapter, rFPGA0_XB_HSSIParameter1|MaskforPhySet, BIT8);
+
+ if (RfPiEnable) {
+ /* Read from BBreg8b8, 12 bits for 8190, 20bits for T65 RF */
+ retValue = PHY_QueryBBReg(Adapter, pPhyReg->rfLSSIReadBackPi|MaskforPhySet, bLSSIReadBackData);
+ } else {
+ /* Read from BBreg8a0, 12 bits for 8190, 20 bits for T65 RF */
+ retValue = PHY_QueryBBReg(Adapter, pPhyReg->rfLSSIReadBack|MaskforPhySet, bLSSIReadBackData);
+ }
+ return retValue;
+
+}
+
+/**
+ * phy_RFSerialWrite_8723B - Write data to RF register (page 8~).
+ * @Adapter:
+ * @eRFPath: Radio path of A/B/C/D
+ * @Offset: The target address to be read
+ * @Data: The new register Data in the target bit position
+ * of the target to be read
+ *
+ * .. Note:: Threre are three types of serial operations:
+ * 1. Software serial write
+ * 2. Hardware LSSI-Low Speed Serial Interface
+ * 3. Hardware HSSI-High speed
+ * serial write. Driver need to implement (1) and (2).
+ * This function is equal to the combination of RF_ReadReg() and RFLSSIRead()
+ *
+ * .. Note:: For RF8256 only
+ * The total count of RTL8256(Zebra4) register is around 36 bit it only employs
+ * 4-bit RF address. RTL8256 uses "register mode control bit" (Reg00[12], Reg00[10])
+ * to access register address bigger than 0xf. See "Appendix-4 in PHY Configuration
+ * programming guide" for more details.
+ * Thus, we define a sub-finction for RTL8526 register address conversion
+ * ===========================================================
+ * Register Mode RegCTL[1] RegCTL[0] Note
+ * (Reg00[12]) (Reg00[10])
+ * ===========================================================
+ * Reg_Mode0 0 x Reg 0 ~15(0x0 ~ 0xf)
+ * ------------------------------------------------------------------
+ * Reg_Mode1 1 0 Reg 16 ~30(0x1 ~ 0xf)
+ * ------------------------------------------------------------------
+ * Reg_Mode2 1 1 Reg 31 ~ 45(0x1 ~ 0xf)
+ * ------------------------------------------------------------------
+ *
+ *2008/09/02 MH Add 92S RF definition
+ *
+ *
+ *
+ */
+static void phy_RFSerialWrite_8723B(
+ struct adapter *Adapter,
+ enum rf_path eRFPath,
+ u32 Offset,
+ u32 Data
+)
+{
+ u32 DataAndAddr = 0;
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+ struct bb_register_def *pPhyReg = &pHalData->PHYRegDef[eRFPath];
+ u32 NewOffset;
+
+ Offset &= 0xff;
+
+ /* */
+ /* Switch page for 8256 RF IC */
+ /* */
+ NewOffset = Offset;
+
+ /* */
+ /* Put write addr in [5:0] and write data in [31:16] */
+ /* */
+ DataAndAddr = ((NewOffset<<20) | (Data&0x000fffff)) & 0x0fffffff; /* T65 RF */
+ /* */
+ /* Write Operation */
+ /* */
+ PHY_SetBBReg(Adapter, pPhyReg->rf3wireOffset, bMaskDWord, DataAndAddr);
+}
+
+
+/**
+ * PHY_QueryRFReg_8723B - Query "Specific bits" to RF register (page 8~).
+ * @Adapter:
+ * @eRFPath: Radio path of A/B/C/D
+ * @RegAddr: The target address to be read
+ * @BitMask: The target bit position in the target address
+ * to be read
+ *
+ * Return: Readback value
+ *
+ * .. Note:: This function is equal to "GetRFRegSetting" in PHY
+ * programming guide
+ */
+u32 PHY_QueryRFReg_8723B(
+ struct adapter *Adapter,
+ u8 eRFPath,
+ u32 RegAddr,
+ u32 BitMask
+)
+{
+ u32 Original_Value, BitShift;
+
+ Original_Value = phy_RFSerialRead_8723B(Adapter, eRFPath, RegAddr);
+ BitShift = phy_CalculateBitShift(BitMask);
+
+ return (Original_Value & BitMask) >> BitShift;
+}
+
+/**
+ * PHY_SetRFReg_8723B - Write "Specific bits" to RF register (page 8~).
+ * @Adapter:
+ * @eRFPath: Radio path of A/B/C/D
+ * @RegAddr: The target address to be modified
+ * @BitMask: The target bit position in the target address
+ * to be modified
+ * @Data: The new register Data in the target bit position
+ * of the target address
+ *
+ * .. Note:: This function is equal to "PutRFRegSetting" in PHY
+ * programming guide.
+ */
+void PHY_SetRFReg_8723B(
+ struct adapter *Adapter,
+ u8 eRFPath,
+ u32 RegAddr,
+ u32 BitMask,
+ u32 Data
+)
+{
+ u32 Original_Value, BitShift;
+
+ /* RF data is 12 bits only */
+ if (BitMask != bRFRegOffsetMask) {
+ Original_Value = phy_RFSerialRead_8723B(Adapter, eRFPath, RegAddr);
+ BitShift = phy_CalculateBitShift(BitMask);
+ Data = ((Original_Value & (~BitMask)) | (Data<<BitShift));
+ }
+
+ phy_RFSerialWrite_8723B(Adapter, eRFPath, RegAddr, Data);
+}
+
+
+/* */
+/* 3. Initial MAC/BB/RF config by reading MAC/BB/RF txt. */
+/* */
+
+
+/*-----------------------------------------------------------------------------
+ * PHY_MACConfig8192C - Condig MAC by header file or parameter file.
+ *
+ * Revised History:
+ * When Who Remark
+ * 08/12/2008 MHC Create Version 0.
+ *
+ *---------------------------------------------------------------------------
+ */
+s32 PHY_MACConfig8723B(struct adapter *Adapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+
+ ODM_ReadAndConfig_MP_8723B_MAC_REG(&pHalData->odmpriv);
+ return _SUCCESS;
+}
+
+/**
+ * phy_InitBBRFRegisterDefinition - Initialize Register definition offset for
+ * Radio Path A/B/C/D
+ * @Adapter:
+ *
+ * .. Note:: The initialization value is constant and it should never be changes
+ */
+static void phy_InitBBRFRegisterDefinition(struct adapter *Adapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+
+ /* RF Interface Sowrtware Control */
+ pHalData->PHYRegDef[RF_PATH_A].rfintfs = rFPGA0_XAB_RFInterfaceSW; /* 16 LSBs if read 32-bit from 0x870 */
+ pHalData->PHYRegDef[RF_PATH_B].rfintfs = rFPGA0_XAB_RFInterfaceSW; /* 16 MSBs if read 32-bit from 0x870 (16-bit for 0x872) */
+
+ /* RF Interface Output (and Enable) */
+ pHalData->PHYRegDef[RF_PATH_A].rfintfo = rFPGA0_XA_RFInterfaceOE; /* 16 LSBs if read 32-bit from 0x860 */
+ pHalData->PHYRegDef[RF_PATH_B].rfintfo = rFPGA0_XB_RFInterfaceOE; /* 16 LSBs if read 32-bit from 0x864 */
+
+ /* RF Interface (Output and) Enable */
+ pHalData->PHYRegDef[RF_PATH_A].rfintfe = rFPGA0_XA_RFInterfaceOE; /* 16 MSBs if read 32-bit from 0x860 (16-bit for 0x862) */
+ pHalData->PHYRegDef[RF_PATH_B].rfintfe = rFPGA0_XB_RFInterfaceOE; /* 16 MSBs if read 32-bit from 0x864 (16-bit for 0x866) */
+
+ pHalData->PHYRegDef[RF_PATH_A].rf3wireOffset = rFPGA0_XA_LSSIParameter; /* LSSI Parameter */
+ pHalData->PHYRegDef[RF_PATH_B].rf3wireOffset = rFPGA0_XB_LSSIParameter;
+
+ pHalData->PHYRegDef[RF_PATH_A].rfHSSIPara2 = rFPGA0_XA_HSSIParameter2; /* wire control parameter2 */
+ pHalData->PHYRegDef[RF_PATH_B].rfHSSIPara2 = rFPGA0_XB_HSSIParameter2; /* wire control parameter2 */
+
+ /* Tranceiver Readback LSSI/HSPI mode */
+ pHalData->PHYRegDef[RF_PATH_A].rfLSSIReadBack = rFPGA0_XA_LSSIReadBack;
+ pHalData->PHYRegDef[RF_PATH_B].rfLSSIReadBack = rFPGA0_XB_LSSIReadBack;
+ pHalData->PHYRegDef[RF_PATH_A].rfLSSIReadBackPi = TransceiverA_HSPI_Readback;
+ pHalData->PHYRegDef[RF_PATH_B].rfLSSIReadBackPi = TransceiverB_HSPI_Readback;
+
+}
+
+static int phy_BB8723b_Config_ParaFile(struct adapter *Adapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+
+ /* Read Tx Power Limit File */
+ PHY_InitTxPowerLimit(Adapter);
+ if (
+ Adapter->registrypriv.RegEnableTxPowerLimit == 1 ||
+ (Adapter->registrypriv.RegEnableTxPowerLimit == 2 && pHalData->EEPROMRegulatory == 1)
+ ) {
+ ODM_ConfigRFWithHeaderFile(&pHalData->odmpriv,
+ CONFIG_RF_TXPWR_LMT, 0);
+ }
+
+ /* */
+ /* 1. Read PHY_REG.TXT BB INIT!! */
+ /* */
+ ODM_ConfigBBWithHeaderFile(&pHalData->odmpriv, CONFIG_BB_PHY_REG);
+
+ /* If EEPROM or EFUSE autoload OK, We must config by PHY_REG_PG.txt */
+ PHY_InitTxPowerByRate(Adapter);
+ if (
+ Adapter->registrypriv.RegEnableTxPowerByRate == 1 ||
+ (Adapter->registrypriv.RegEnableTxPowerByRate == 2 && pHalData->EEPROMRegulatory != 2)
+ ) {
+ ODM_ConfigBBWithHeaderFile(&pHalData->odmpriv,
+ CONFIG_BB_PHY_REG_PG);
+
+ if (pHalData->odmpriv.PhyRegPgValueType == PHY_REG_PG_EXACT_VALUE)
+ PHY_TxPowerByRateConfiguration(Adapter);
+
+ if (
+ Adapter->registrypriv.RegEnableTxPowerLimit == 1 ||
+ (Adapter->registrypriv.RegEnableTxPowerLimit == 2 && pHalData->EEPROMRegulatory == 1)
+ )
+ PHY_ConvertTxPowerLimitToPowerIndex(Adapter);
+ }
+
+ /* */
+ /* 2. Read BB AGC table Initialization */
+ /* */
+ ODM_ConfigBBWithHeaderFile(&pHalData->odmpriv, CONFIG_BB_AGC_TAB);
+
+ return _SUCCESS;
+}
+
+
+int PHY_BBConfig8723B(struct adapter *Adapter)
+{
+ int rtStatus = _SUCCESS;
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+ u32 RegVal;
+ u8 CrystalCap;
+
+ phy_InitBBRFRegisterDefinition(Adapter);
+
+ /* Enable BB and RF */
+ RegVal = rtw_read16(Adapter, REG_SYS_FUNC_EN);
+ rtw_write16(Adapter, REG_SYS_FUNC_EN, (u16)(RegVal|BIT13|BIT0|BIT1));
+
+ rtw_write32(Adapter, 0x948, 0x280); /* Others use Antenna S1 */
+
+ rtw_write8(Adapter, REG_RF_CTRL, RF_EN|RF_RSTB|RF_SDMRSTB);
+
+ msleep(1);
+
+ PHY_SetRFReg(Adapter, RF_PATH_A, 0x1, 0xfffff, 0x780);
+
+ rtw_write8(Adapter, REG_SYS_FUNC_EN, FEN_PPLL|FEN_PCIEA|FEN_DIO_PCIE|FEN_BB_GLB_RSTn|FEN_BBRSTB);
+
+ rtw_write8(Adapter, REG_AFE_XTAL_CTRL+1, 0x80);
+
+ /* */
+ /* Config BB and AGC */
+ /* */
+ rtStatus = phy_BB8723b_Config_ParaFile(Adapter);
+
+ /* 0x2C[23:18] = 0x2C[17:12] = CrystalCap */
+ CrystalCap = pHalData->CrystalCap & 0x3F;
+ PHY_SetBBReg(Adapter, REG_MAC_PHY_CTRL, 0xFFF000, (CrystalCap | (CrystalCap << 6)));
+
+ return rtStatus;
+}
+
+static void phy_LCK_8723B(struct adapter *Adapter)
+{
+ PHY_SetRFReg(Adapter, RF_PATH_A, 0xB0, bRFRegOffsetMask, 0xDFBE0);
+ PHY_SetRFReg(Adapter, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, 0x8C01);
+ mdelay(200);
+ PHY_SetRFReg(Adapter, RF_PATH_A, 0xB0, bRFRegOffsetMask, 0xDFFE0);
+}
+
+int PHY_RFConfig8723B(struct adapter *Adapter)
+{
+ int rtStatus = _SUCCESS;
+
+ /* */
+ /* RF config */
+ /* */
+ rtStatus = PHY_RF6052_Config8723B(Adapter);
+
+ phy_LCK_8723B(Adapter);
+
+ return rtStatus;
+}
+
+/**************************************************************************************************************
+ * Description:
+ * The low-level interface to set TxAGC , called by both MP and Normal Driver.
+ *
+ * <20120830, Kordan>
+ **************************************************************************************************************/
+
+void PHY_SetTxPowerIndex(
+ struct adapter *Adapter,
+ u32 PowerIndex,
+ u8 RFPath,
+ u8 Rate
+)
+{
+ if (RFPath == RF_PATH_A || RFPath == RF_PATH_B) {
+ switch (Rate) {
+ case MGN_1M:
+ PHY_SetBBReg(Adapter, rTxAGC_A_CCK1_Mcs32, bMaskByte1, PowerIndex);
+ break;
+ case MGN_2M:
+ PHY_SetBBReg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, bMaskByte1, PowerIndex);
+ break;
+ case MGN_5_5M:
+ PHY_SetBBReg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, bMaskByte2, PowerIndex);
+ break;
+ case MGN_11M:
+ PHY_SetBBReg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, bMaskByte3, PowerIndex);
+ break;
+
+ case MGN_6M:
+ PHY_SetBBReg(Adapter, rTxAGC_A_Rate18_06, bMaskByte0, PowerIndex);
+ break;
+ case MGN_9M:
+ PHY_SetBBReg(Adapter, rTxAGC_A_Rate18_06, bMaskByte1, PowerIndex);
+ break;
+ case MGN_12M:
+ PHY_SetBBReg(Adapter, rTxAGC_A_Rate18_06, bMaskByte2, PowerIndex);
+ break;
+ case MGN_18M:
+ PHY_SetBBReg(Adapter, rTxAGC_A_Rate18_06, bMaskByte3, PowerIndex);
+ break;
+
+ case MGN_24M:
+ PHY_SetBBReg(Adapter, rTxAGC_A_Rate54_24, bMaskByte0, PowerIndex);
+ break;
+ case MGN_36M:
+ PHY_SetBBReg(Adapter, rTxAGC_A_Rate54_24, bMaskByte1, PowerIndex);
+ break;
+ case MGN_48M:
+ PHY_SetBBReg(Adapter, rTxAGC_A_Rate54_24, bMaskByte2, PowerIndex);
+ break;
+ case MGN_54M:
+ PHY_SetBBReg(Adapter, rTxAGC_A_Rate54_24, bMaskByte3, PowerIndex);
+ break;
+
+ case MGN_MCS0:
+ PHY_SetBBReg(Adapter, rTxAGC_A_Mcs03_Mcs00, bMaskByte0, PowerIndex);
+ break;
+ case MGN_MCS1:
+ PHY_SetBBReg(Adapter, rTxAGC_A_Mcs03_Mcs00, bMaskByte1, PowerIndex);
+ break;
+ case MGN_MCS2:
+ PHY_SetBBReg(Adapter, rTxAGC_A_Mcs03_Mcs00, bMaskByte2, PowerIndex);
+ break;
+ case MGN_MCS3:
+ PHY_SetBBReg(Adapter, rTxAGC_A_Mcs03_Mcs00, bMaskByte3, PowerIndex);
+ break;
+
+ case MGN_MCS4:
+ PHY_SetBBReg(Adapter, rTxAGC_A_Mcs07_Mcs04, bMaskByte0, PowerIndex);
+ break;
+ case MGN_MCS5:
+ PHY_SetBBReg(Adapter, rTxAGC_A_Mcs07_Mcs04, bMaskByte1, PowerIndex);
+ break;
+ case MGN_MCS6:
+ PHY_SetBBReg(Adapter, rTxAGC_A_Mcs07_Mcs04, bMaskByte2, PowerIndex);
+ break;
+ case MGN_MCS7:
+ PHY_SetBBReg(Adapter, rTxAGC_A_Mcs07_Mcs04, bMaskByte3, PowerIndex);
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+u8 PHY_GetTxPowerIndex(
+ struct adapter *padapter,
+ u8 RFPath,
+ u8 Rate,
+ enum channel_width BandWidth,
+ u8 Channel
+)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ s8 txPower = 0, powerDiffByRate = 0, limit = 0;
+
+ txPower = (s8) PHY_GetTxPowerIndexBase(padapter, RFPath, Rate, BandWidth, Channel);
+ powerDiffByRate = PHY_GetTxPowerByRate(padapter, RF_PATH_A, Rate);
+
+ limit = phy_get_tx_pwr_lmt(
+ padapter,
+ padapter->registrypriv.RegPwrTblSel,
+ pHalData->CurrentChannelBW,
+ RFPath,
+ Rate,
+ pHalData->CurrentChannel
+ );
+
+ powerDiffByRate = powerDiffByRate > limit ? limit : powerDiffByRate;
+ txPower += powerDiffByRate;
+
+ txPower += PHY_GetTxPowerTrackingOffset(padapter, RFPath, Rate);
+
+ if (txPower > MAX_POWER_INDEX)
+ txPower = MAX_POWER_INDEX;
+
+ return (u8) txPower;
+}
+
+void PHY_SetTxPowerLevel8723B(struct adapter *Adapter, u8 Channel)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+ struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
+ struct fat_t *pDM_FatTable = &pDM_Odm->DM_FatTable;
+ u8 RFPath = RF_PATH_A;
+
+ if (pHalData->AntDivCfg) {/* antenna diversity Enable */
+ RFPath = ((pDM_FatTable->RxIdleAnt == MAIN_ANT) ? RF_PATH_A : RF_PATH_B);
+ } else { /* antenna diversity disable */
+ RFPath = pHalData->ant_path;
+ }
+
+ PHY_SetTxPowerLevelByPath(Adapter, Channel, RFPath);
+}
+
+void PHY_GetTxPowerLevel8723B(struct adapter *Adapter, s32 *powerlevel)
+{
+}
+
+static void phy_SetRegBW_8723B(
+ struct adapter *Adapter, enum channel_width CurrentBW
+)
+{
+ u16 RegRfMod_BW, u2tmp = 0;
+ RegRfMod_BW = rtw_read16(Adapter, REG_TRXPTCL_CTL_8723B);
+
+ switch (CurrentBW) {
+ case CHANNEL_WIDTH_20:
+ rtw_write16(Adapter, REG_TRXPTCL_CTL_8723B, (RegRfMod_BW & 0xFE7F)); /* BIT 7 = 0, BIT 8 = 0 */
+ break;
+
+ case CHANNEL_WIDTH_40:
+ u2tmp = RegRfMod_BW | BIT7;
+ rtw_write16(Adapter, REG_TRXPTCL_CTL_8723B, (u2tmp & 0xFEFF)); /* BIT 7 = 1, BIT 8 = 0 */
+ break;
+
+ default:
+ break;
+ }
+}
+
+static u8 phy_GetSecondaryChnl_8723B(struct adapter *Adapter)
+{
+ u8 SCSettingOf40 = 0, SCSettingOf20 = 0;
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+
+ if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_40) {
+ if (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER)
+ SCSettingOf20 = HT_DATA_SC_20_UPPER_OF_40MHZ;
+ else if (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER)
+ SCSettingOf20 = HT_DATA_SC_20_LOWER_OF_40MHZ;
+ }
+
+ return (SCSettingOf40 << 4) | SCSettingOf20;
+}
+
+static void phy_PostSetBwMode8723B(struct adapter *Adapter)
+{
+ u8 SubChnlNum = 0;
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+
+
+ /* 3 Set Reg668 Reg440 BW */
+ phy_SetRegBW_8723B(Adapter, pHalData->CurrentChannelBW);
+
+ /* 3 Set Reg483 */
+ SubChnlNum = phy_GetSecondaryChnl_8723B(Adapter);
+ rtw_write8(Adapter, REG_DATA_SC_8723B, SubChnlNum);
+
+ /* 3 */
+ /* 3<2>Set PHY related register */
+ /* 3 */
+ switch (pHalData->CurrentChannelBW) {
+ /* 20 MHz channel*/
+ case CHANNEL_WIDTH_20:
+ PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bRFMOD, 0x0);
+
+ PHY_SetBBReg(Adapter, rFPGA1_RFMOD, bRFMOD, 0x0);
+
+ PHY_SetBBReg(Adapter, rOFDM0_TxPseudoNoiseWgt, (BIT31|BIT30), 0x0);
+ break;
+
+ /* 40 MHz channel*/
+ case CHANNEL_WIDTH_40:
+ PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bRFMOD, 0x1);
+
+ PHY_SetBBReg(Adapter, rFPGA1_RFMOD, bRFMOD, 0x1);
+
+ /* Set Control channel to upper or lower. These settings are required only for 40MHz */
+ PHY_SetBBReg(Adapter, rCCK0_System, bCCKSideBand, (pHalData->nCur40MhzPrimeSC>>1));
+
+ PHY_SetBBReg(Adapter, rOFDM1_LSTF, 0xC00, pHalData->nCur40MhzPrimeSC);
+
+ PHY_SetBBReg(Adapter, 0x818, (BIT26|BIT27), (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
+ break;
+ default:
+ break;
+ }
+
+ /* 3<3>Set RF related register */
+ PHY_RF6052SetBandwidth8723B(Adapter, pHalData->CurrentChannelBW);
+}
+
+static void phy_SwChnl8723B(struct adapter *padapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ u8 channelToSW = pHalData->CurrentChannel;
+
+ if (pHalData->rf_chip == RF_PSEUDO_11N)
+ return;
+ pHalData->RfRegChnlVal[0] = ((pHalData->RfRegChnlVal[0] & 0xfffff00) | channelToSW);
+ PHY_SetRFReg(padapter, RF_PATH_A, RF_CHNLBW, 0x3FF, pHalData->RfRegChnlVal[0]);
+ PHY_SetRFReg(padapter, RF_PATH_B, RF_CHNLBW, 0x3FF, pHalData->RfRegChnlVal[0]);
+}
+
+static void phy_SwChnlAndSetBwMode8723B(struct adapter *Adapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+
+ if (Adapter->bDriverStopped || Adapter->bSurpriseRemoved)
+ return;
+
+ if (pHalData->bSwChnl) {
+ phy_SwChnl8723B(Adapter);
+ pHalData->bSwChnl = false;
+ }
+
+ if (pHalData->bSetChnlBW) {
+ phy_PostSetBwMode8723B(Adapter);
+ pHalData->bSetChnlBW = false;
+ }
+
+ PHY_SetTxPowerLevel8723B(Adapter, pHalData->CurrentChannel);
+}
+
+static void PHY_HandleSwChnlAndSetBW8723B(
+ struct adapter *Adapter,
+ bool bSwitchChannel,
+ bool bSetBandWidth,
+ u8 ChannelNum,
+ enum channel_width ChnlWidth,
+ enum extchnl_offset ExtChnlOffsetOf40MHz,
+ enum extchnl_offset ExtChnlOffsetOf80MHz,
+ u8 CenterFrequencyIndex1
+)
+{
+ /* static bool bInitialzed = false; */
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+ u8 tmpChannel = pHalData->CurrentChannel;
+ enum channel_width tmpBW = pHalData->CurrentChannelBW;
+ u8 tmpnCur40MhzPrimeSC = pHalData->nCur40MhzPrimeSC;
+ u8 tmpnCur80MhzPrimeSC = pHalData->nCur80MhzPrimeSC;
+ u8 tmpCenterFrequencyIndex1 = pHalData->CurrentCenterFrequencyIndex1;
+
+ /* check is swchnl or setbw */
+ if (!bSwitchChannel && !bSetBandWidth)
+ return;
+
+ /* skip change for channel or bandwidth is the same */
+ if (bSwitchChannel) {
+ {
+ if (HAL_IsLegalChannel(Adapter, ChannelNum))
+ pHalData->bSwChnl = true;
+ }
+ }
+
+ if (bSetBandWidth)
+ pHalData->bSetChnlBW = true;
+
+ if (!pHalData->bSetChnlBW && !pHalData->bSwChnl)
+ return;
+
+
+ if (pHalData->bSwChnl) {
+ pHalData->CurrentChannel = ChannelNum;
+ pHalData->CurrentCenterFrequencyIndex1 = ChannelNum;
+ }
+
+
+ if (pHalData->bSetChnlBW) {
+ pHalData->CurrentChannelBW = ChnlWidth;
+ pHalData->nCur40MhzPrimeSC = ExtChnlOffsetOf40MHz;
+ pHalData->nCur80MhzPrimeSC = ExtChnlOffsetOf80MHz;
+ pHalData->CurrentCenterFrequencyIndex1 = CenterFrequencyIndex1;
+ }
+
+ /* Switch workitem or set timer to do switch channel or setbandwidth operation */
+ if ((!Adapter->bDriverStopped) && (!Adapter->bSurpriseRemoved)) {
+ phy_SwChnlAndSetBwMode8723B(Adapter);
+ } else {
+ if (pHalData->bSwChnl) {
+ pHalData->CurrentChannel = tmpChannel;
+ pHalData->CurrentCenterFrequencyIndex1 = tmpChannel;
+ }
+
+ if (pHalData->bSetChnlBW) {
+ pHalData->CurrentChannelBW = tmpBW;
+ pHalData->nCur40MhzPrimeSC = tmpnCur40MhzPrimeSC;
+ pHalData->nCur80MhzPrimeSC = tmpnCur80MhzPrimeSC;
+ pHalData->CurrentCenterFrequencyIndex1 = tmpCenterFrequencyIndex1;
+ }
+ }
+}
+
+void PHY_SetBWMode8723B(
+ struct adapter *Adapter,
+ enum channel_width Bandwidth, /* 20M or 40M */
+ unsigned char Offset /* Upper, Lower, or Don't care */
+)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+
+ PHY_HandleSwChnlAndSetBW8723B(Adapter, false, true, pHalData->CurrentChannel, Bandwidth, Offset, Offset, pHalData->CurrentChannel);
+}
+
+/* Call after initialization */
+void PHY_SwChnl8723B(struct adapter *Adapter, u8 channel)
+{
+ PHY_HandleSwChnlAndSetBW8723B(Adapter, true, false, channel, 0, 0, 0, channel);
+}
+
+void PHY_SetSwChnlBWMode8723B(
+ struct adapter *Adapter,
+ u8 channel,
+ enum channel_width Bandwidth,
+ u8 Offset40,
+ u8 Offset80
+)
+{
+ PHY_HandleSwChnlAndSetBW8723B(Adapter, true, true, channel, Bandwidth, Offset40, Offset80, channel);
+}
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_rf6052.c b/drivers/staging/rtl8723bs/hal/rtl8723b_rf6052.c
new file mode 100644
index 000000000..ffb35e1ac
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/rtl8723b_rf6052.c
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+/******************************************************************************
+ *
+ *
+ * Module: rtl8192c_rf6052.c (Source C File)
+ *
+ * Note: Provide RF 6052 series relative API.
+ *
+ * Function:
+ *
+ * Export:
+ *
+ * Abbrev:
+ *
+ * History:
+ * Data Who Remark
+ *
+ * 09/25/2008 MHC Create initial version.
+ * 11/05/2008 MHC Add API for tw power setting.
+ *
+ *
+******************************************************************************/
+
+#include <rtl8723b_hal.h>
+
+/*---------------------------Define Local Constant---------------------------*/
+/*---------------------------Define Local Constant---------------------------*/
+
+
+/*------------------------Define global variable-----------------------------*/
+/*------------------------Define global variable-----------------------------*/
+
+
+/*------------------------Define local variable------------------------------*/
+/* 2008/11/20 MH For Debug only, RF */
+/*------------------------Define local variable------------------------------*/
+
+/*-----------------------------------------------------------------------------
+ * Function: PHY_RF6052SetBandwidth()
+ *
+ * Overview: This function is called by SetBWModeCallback8190Pci() only
+ *
+ * Input: struct adapter * Adapter
+ * WIRELESS_BANDWIDTH_E Bandwidth 20M or 40M
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ *
+ * Note: For RF type 0222D
+ *---------------------------------------------------------------------------*/
+void PHY_RF6052SetBandwidth8723B(
+ struct adapter *Adapter, enum channel_width Bandwidth
+) /* 20M or 40M */
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+
+ switch (Bandwidth) {
+ case CHANNEL_WIDTH_20:
+ pHalData->RfRegChnlVal[0] = ((pHalData->RfRegChnlVal[0] & 0xfffff3ff) | BIT10 | BIT11);
+ PHY_SetRFReg(Adapter, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal[0]);
+ PHY_SetRFReg(Adapter, RF_PATH_B, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal[0]);
+ break;
+
+ case CHANNEL_WIDTH_40:
+ pHalData->RfRegChnlVal[0] = ((pHalData->RfRegChnlVal[0] & 0xfffff3ff) | BIT10);
+ PHY_SetRFReg(Adapter, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal[0]);
+ PHY_SetRFReg(Adapter, RF_PATH_B, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal[0]);
+ break;
+
+ default:
+ break;
+ }
+
+}
+
+static int phy_RF6052_Config_ParaFile(struct adapter *Adapter)
+{
+ u32 u4RegValue = 0;
+ u8 eRFPath;
+ struct bb_register_def *pPhyReg;
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+
+ /* 3----------------------------------------------------------------- */
+ /* 3 <2> Initialize RF */
+ /* 3----------------------------------------------------------------- */
+ /* for (eRFPath = RF_PATH_A; eRFPath <pHalData->NumTotalRFPath; eRFPath++) */
+ for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++) {
+
+ pPhyReg = &pHalData->PHYRegDef[eRFPath];
+
+ /*----Store original RFENV control type----*/
+ switch (eRFPath) {
+ case RF_PATH_A:
+ u4RegValue = PHY_QueryBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV);
+ break;
+ case RF_PATH_B:
+ u4RegValue = PHY_QueryBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV << 16);
+ break;
+ }
+
+ /*----Set RF_ENV enable----*/
+ PHY_SetBBReg(Adapter, pPhyReg->rfintfe, bRFSI_RFENV << 16, 0x1);
+ udelay(1);/* PlatformStallExecution(1); */
+
+ /*----Set RF_ENV output high----*/
+ PHY_SetBBReg(Adapter, pPhyReg->rfintfo, bRFSI_RFENV, 0x1);
+ udelay(1);/* PlatformStallExecution(1); */
+
+ /* Set bit number of Address and Data for RF register */
+ PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, b3WireAddressLength, 0x0); /* Set 1 to 4 bits for 8255 */
+ udelay(1);/* PlatformStallExecution(1); */
+
+ PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, b3WireDataLength, 0x0); /* Set 0 to 12 bits for 8255 */
+ udelay(1);/* PlatformStallExecution(1); */
+
+ /*----Initialize RF fom connfiguration file----*/
+ switch (eRFPath) {
+ case RF_PATH_A:
+ case RF_PATH_B:
+ ODM_ConfigRFWithHeaderFile(&pHalData->odmpriv,
+ CONFIG_RF_RADIO, eRFPath);
+ break;
+ }
+
+ /*----Restore RFENV control type----*/
+ switch (eRFPath) {
+ case RF_PATH_A:
+ PHY_SetBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV, u4RegValue);
+ break;
+ case RF_PATH_B:
+ PHY_SetBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV << 16, u4RegValue);
+ break;
+ }
+ }
+
+ /* 3 ----------------------------------------------------------------- */
+ /* 3 Configuration of Tx Power Tracking */
+ /* 3 ----------------------------------------------------------------- */
+
+ ODM_ConfigRFWithTxPwrTrackHeaderFile(&pHalData->odmpriv);
+
+ return _SUCCESS;
+}
+
+
+int PHY_RF6052_Config8723B(struct adapter *Adapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+
+ /* */
+ /* Initialize general global value */
+ /* */
+ pHalData->NumTotalRFPath = 1;
+
+ /* */
+ /* Config BB and RF */
+ /* */
+ return phy_RF6052_Config_ParaFile(Adapter);
+
+}
+
+/* End of HalRf6052.c */
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_rxdesc.c b/drivers/staging/rtl8723bs/hal/rtl8723b_rxdesc.c
new file mode 100644
index 000000000..717faebf8
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/rtl8723b_rxdesc.c
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include <rtl8723b_hal.h>
+
+static void process_rssi(struct adapter *padapter, union recv_frame *prframe)
+{
+ struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
+ struct signal_stat *signal_stat = &padapter->recvpriv.signal_strength_data;
+
+ /* if (pRfd->Status.bPacketToSelf || pRfd->Status.bPacketBeacon) */
+ {
+ if (signal_stat->update_req) {
+ signal_stat->total_num = 0;
+ signal_stat->total_val = 0;
+ signal_stat->update_req = 0;
+ }
+
+ signal_stat->total_num++;
+ signal_stat->total_val += pattrib->phy_info.SignalStrength;
+ signal_stat->avg_val = signal_stat->total_val / signal_stat->total_num;
+ }
+
+} /* Process_UI_RSSI_8192C */
+
+static void process_link_qual(struct adapter *padapter, union recv_frame *prframe)
+{
+ struct rx_pkt_attrib *pattrib;
+ struct signal_stat *signal_stat;
+
+ if (!prframe || !padapter)
+ return;
+
+ pattrib = &prframe->u.hdr.attrib;
+ signal_stat = &padapter->recvpriv.signal_qual_data;
+
+ if (signal_stat->update_req) {
+ signal_stat->total_num = 0;
+ signal_stat->total_val = 0;
+ signal_stat->update_req = 0;
+ }
+
+ signal_stat->total_num++;
+ signal_stat->total_val += pattrib->phy_info.SignalQuality;
+ signal_stat->avg_val = signal_stat->total_val / signal_stat->total_num;
+} /* Process_UiLinkQuality8192S */
+
+
+void rtl8723b_process_phy_info(struct adapter *padapter, void *prframe)
+{
+ union recv_frame *precvframe = prframe;
+ /* */
+ /* Check RSSI */
+ /* */
+ process_rssi(padapter, precvframe);
+ /* */
+ /* Check PWDB. */
+ /* */
+ /* process_PWDB(padapter, precvframe); */
+
+ /* UpdateRxSignalStatistics8192C(Adapter, pRfd); */
+ /* */
+ /* Check EVM */
+ /* */
+ process_link_qual(padapter, precvframe);
+ #ifdef DBG_RX_SIGNAL_DISPLAY_RAW_DATA
+ rtw_store_phy_info(padapter, prframe);
+ #endif
+
+}
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c b/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c
new file mode 100644
index 000000000..74e75dc97
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c
@@ -0,0 +1,479 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include <drv_types.h>
+#include <rtw_debug.h>
+#include <rtl8723b_hal.h>
+
+static void initrecvbuf(struct recv_buf *precvbuf, struct adapter *padapter)
+{
+ INIT_LIST_HEAD(&precvbuf->list);
+ spin_lock_init(&precvbuf->recvbuf_lock);
+
+ precvbuf->adapter = padapter;
+}
+
+static void update_recvframe_attrib(struct adapter *padapter,
+ union recv_frame *precvframe,
+ struct recv_stat *prxstat)
+{
+ struct rx_pkt_attrib *pattrib;
+ struct recv_stat report;
+ struct rxreport_8723b *prxreport = (struct rxreport_8723b *)&report;
+
+ report.rxdw0 = prxstat->rxdw0;
+ report.rxdw1 = prxstat->rxdw1;
+ report.rxdw2 = prxstat->rxdw2;
+ report.rxdw3 = prxstat->rxdw3;
+ report.rxdw4 = prxstat->rxdw4;
+ report.rxdw5 = prxstat->rxdw5;
+
+ pattrib = &precvframe->u.hdr.attrib;
+ memset(pattrib, 0, sizeof(struct rx_pkt_attrib));
+
+ /* update rx report to recv_frame attribute */
+ pattrib->pkt_rpt_type = prxreport->c2h_ind ? C2H_PACKET : NORMAL_RX;
+
+ if (pattrib->pkt_rpt_type == NORMAL_RX) {
+ /* Normal rx packet */
+ /* update rx report to recv_frame attribute */
+ pattrib->pkt_len = (u16)prxreport->pktlen;
+ pattrib->drvinfo_sz = (u8)(prxreport->drvinfosize << 3);
+ pattrib->physt = (u8)prxreport->physt;
+
+ pattrib->crc_err = (u8)prxreport->crc32;
+ pattrib->icv_err = (u8)prxreport->icverr;
+
+ pattrib->bdecrypted = (u8)(prxreport->swdec ? 0 : 1);
+ pattrib->encrypt = (u8)prxreport->security;
+
+ pattrib->qos = (u8)prxreport->qos;
+ pattrib->priority = (u8)prxreport->tid;
+
+ pattrib->amsdu = (u8)prxreport->amsdu;
+
+ pattrib->seq_num = (u16)prxreport->seq;
+ pattrib->frag_num = (u8)prxreport->frag;
+ pattrib->mfrag = (u8)prxreport->mf;
+ pattrib->mdata = (u8)prxreport->md;
+
+ pattrib->data_rate = (u8)prxreport->rx_rate;
+ } else {
+ pattrib->pkt_len = (u16)prxreport->pktlen;
+ }
+}
+
+/*
+ * Notice:
+ *Before calling this function,
+ *precvframe->u.hdr.rx_data should be ready!
+ */
+static void update_recvframe_phyinfo(union recv_frame *precvframe,
+ struct phy_stat *pphy_status)
+{
+ struct adapter *padapter = precvframe->u.hdr.adapter;
+ struct rx_pkt_attrib *pattrib = &precvframe->u.hdr.attrib;
+ struct hal_com_data *p_hal_data = GET_HAL_DATA(padapter);
+ struct odm_phy_info *p_phy_info =
+ (struct odm_phy_info *)(&pattrib->phy_info);
+
+ u8 *wlanhdr = precvframe->u.hdr.rx_data;
+ u8 *my_bssid;
+ u8 *rx_bssid;
+ u8 *rx_ra;
+ u8 *my_hwaddr;
+ u8 *sa = NULL;
+
+ struct odm_packet_info pkt_info = {
+ .data_rate = 0x00,
+ .station_id = 0x00,
+ .bssid_match = false,
+ .to_self = false,
+ .is_beacon = false,
+ };
+
+ /* unsigned long irqL; */
+ struct sta_priv *pstapriv;
+ struct sta_info *psta;
+
+ my_bssid = get_bssid(&padapter->mlmepriv);
+ rx_bssid = get_hdr_bssid(wlanhdr);
+ pkt_info.bssid_match = ((!IsFrameTypeCtrl(wlanhdr)) &&
+ !pattrib->icv_err && !pattrib->crc_err &&
+ ether_addr_equal(rx_bssid, my_bssid));
+
+ rx_ra = rtl8723bs_get_ra(wlanhdr);
+ my_hwaddr = myid(&padapter->eeprompriv);
+ pkt_info.to_self = pkt_info.bssid_match &&
+ ether_addr_equal(rx_ra, my_hwaddr);
+
+
+ pkt_info.is_beacon = pkt_info.bssid_match &&
+ (GetFrameSubType(wlanhdr) == WIFI_BEACON);
+
+ sa = get_ta(wlanhdr);
+
+ pkt_info.station_id = 0xFF;
+
+ pstapriv = &padapter->stapriv;
+ psta = rtw_get_stainfo(pstapriv, sa);
+ if (psta)
+ pkt_info.station_id = psta->mac_id;
+
+ pkt_info.data_rate = pattrib->data_rate;
+
+ /* rtl8723b_query_rx_phy_status(precvframe, pphy_status); */
+ /* spin_lock_bh(&p_hal_data->odm_stainfo_lock); */
+ odm_phy_status_query(&p_hal_data->odmpriv, p_phy_info,
+ (u8 *)pphy_status, &(pkt_info));
+ if (psta)
+ psta->rssi = pattrib->phy_info.RecvSignalPower;
+ /* spin_unlock_bh(&p_hal_data->odm_stainfo_lock); */
+ precvframe->u.hdr.psta = NULL;
+ if (
+ pkt_info.bssid_match &&
+ (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true)
+ ) {
+ if (psta) {
+ precvframe->u.hdr.psta = psta;
+ rtl8723b_process_phy_info(padapter, precvframe);
+ }
+ } else if (pkt_info.to_self || pkt_info.is_beacon) {
+ u32 adhoc_state = WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE;
+ if (check_fwstate(&padapter->mlmepriv, adhoc_state))
+ if (psta)
+ precvframe->u.hdr.psta = psta;
+ rtl8723b_process_phy_info(padapter, precvframe);
+ }
+}
+
+static void rtl8723bs_c2h_packet_handler(struct adapter *padapter,
+ u8 *pbuf, u16 length)
+{
+ u8 *tmp = NULL;
+ u8 res = false;
+
+ if (length == 0)
+ return;
+
+ tmp = rtw_zmalloc(length);
+ if (!tmp)
+ return;
+
+ memcpy(tmp, pbuf, length);
+
+ res = rtw_c2h_packet_wk_cmd(padapter, tmp, length);
+
+ if (!res)
+ kfree(tmp);
+}
+
+static inline union recv_frame *try_alloc_recvframe(struct recv_priv *precvpriv,
+ struct recv_buf *precvbuf)
+{
+ union recv_frame *precvframe;
+
+ precvframe = rtw_alloc_recvframe(&precvpriv->free_recv_queue);
+ if (!precvframe) {
+ rtw_enqueue_recvbuf_to_head(precvbuf,
+ &precvpriv->recv_buf_pending_queue);
+
+ /* The case of can't allocate recvframe should be temporary, */
+ /* schedule again and hope recvframe is available next time. */
+ tasklet_schedule(&precvpriv->recv_tasklet);
+ }
+
+ return precvframe;
+}
+
+static inline bool rx_crc_err(struct recv_priv *precvpriv,
+ struct hal_com_data *p_hal_data,
+ struct rx_pkt_attrib *pattrib,
+ union recv_frame *precvframe)
+{
+ /* fix Hardware RX data error, drop whole recv_buffer */
+ if ((!(p_hal_data->ReceiveConfig & RCR_ACRC32)) && pattrib->crc_err) {
+ rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
+ return true;
+ }
+
+ return false;
+}
+
+static inline bool pkt_exceeds_tail(struct recv_priv *precvpriv,
+ u8 *end, u8 *tail,
+ union recv_frame *precvframe)
+{
+ if (end > tail) {
+ rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
+ return true;
+ }
+
+ return false;
+}
+
+static void rtl8723bs_recv_tasklet(struct tasklet_struct *t)
+{
+ struct adapter *padapter = from_tasklet(padapter, t,
+ recvpriv.recv_tasklet);
+ struct hal_com_data *p_hal_data;
+ struct recv_priv *precvpriv;
+ struct recv_buf *precvbuf;
+ union recv_frame *precvframe;
+ struct rx_pkt_attrib *pattrib;
+ struct __queue *recv_buf_queue;
+ u8 *ptr;
+ u32 pkt_offset, skb_len, alloc_sz;
+ struct sk_buff *pkt_copy = NULL;
+ u8 shift_sz = 0, rx_report_sz = 0;
+
+ p_hal_data = GET_HAL_DATA(padapter);
+ precvpriv = &padapter->recvpriv;
+ recv_buf_queue = &precvpriv->recv_buf_pending_queue;
+
+ do {
+ precvbuf = rtw_dequeue_recvbuf(recv_buf_queue);
+ if (!precvbuf)
+ break;
+
+ ptr = precvbuf->pdata;
+
+ while (ptr < precvbuf->ptail) {
+ precvframe = try_alloc_recvframe(precvpriv, precvbuf);
+ if (!precvframe)
+ return;
+
+ /* rx desc parsing */
+ update_recvframe_attrib(padapter, precvframe,
+ (struct recv_stat *)ptr);
+
+ pattrib = &precvframe->u.hdr.attrib;
+
+ if (rx_crc_err(precvpriv, p_hal_data,
+ pattrib, precvframe))
+ break;
+
+ rx_report_sz = RXDESC_SIZE + pattrib->drvinfo_sz;
+ pkt_offset = rx_report_sz +
+ pattrib->shift_sz +
+ pattrib->pkt_len;
+
+ if (pkt_exceeds_tail(precvpriv, ptr + pkt_offset,
+ precvbuf->ptail, precvframe))
+ break;
+
+ if ((pattrib->crc_err) || (pattrib->icv_err)) {
+ rtw_free_recvframe(precvframe,
+ &precvpriv->free_recv_queue);
+ } else {
+ /* Modified by Albert 20101213 */
+ /* For 8 bytes IP header alignment. */
+ if (pattrib->qos) /* Qos data, wireless lan header length is 26 */
+ shift_sz = 6;
+ else
+ shift_sz = 0;
+
+ skb_len = pattrib->pkt_len;
+
+ /* for first fragment packet, driver need allocate 1536+drvinfo_sz+RXDESC_SIZE to defrag packet. */
+ /* modify alloc_sz for recvive crc error packet by thomas 2011-06-02 */
+ if ((pattrib->mfrag == 1) && (pattrib->frag_num == 0)) {
+ if (skb_len <= 1650)
+ alloc_sz = 1664;
+ else
+ alloc_sz = skb_len + 14;
+ } else {
+ alloc_sz = skb_len;
+ /* 6 is for IP header 8 bytes alignment in QoS packet case. */
+ /* 8 is for skb->data 4 bytes alignment. */
+ alloc_sz += 14;
+ }
+
+ pkt_copy = rtw_skb_alloc(alloc_sz);
+ if (!pkt_copy) {
+ rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
+ break;
+ }
+
+ pkt_copy->dev = padapter->pnetdev;
+ precvframe->u.hdr.pkt = pkt_copy;
+ skb_reserve(pkt_copy, 8 - ((SIZE_PTR)(pkt_copy->data) & 7));/* force pkt_copy->data at 8-byte alignment address */
+ skb_reserve(pkt_copy, shift_sz);/* force ip_hdr at 8-byte alignment address according to shift_sz. */
+ memcpy(pkt_copy->data, (ptr + rx_report_sz + pattrib->shift_sz), skb_len);
+ precvframe->u.hdr.rx_head = pkt_copy->head;
+ precvframe->u.hdr.rx_data = precvframe->u.hdr.rx_tail = pkt_copy->data;
+ precvframe->u.hdr.rx_end = skb_end_pointer(pkt_copy);
+
+ recvframe_put(precvframe, skb_len);
+ /* recvframe_pull(precvframe, drvinfo_sz + RXDESC_SIZE); */
+
+ if (p_hal_data->ReceiveConfig & RCR_APPFCS)
+ recvframe_pull_tail(precvframe, IEEE80211_FCS_LEN);
+
+ /* move to drv info position */
+ ptr += RXDESC_SIZE;
+
+ /* update drv info */
+ if (p_hal_data->ReceiveConfig & RCR_APP_BA_SSN) {
+ /* rtl8723s_update_bassn(padapter, pdrvinfo); */
+ ptr += 4;
+ }
+
+ if (pattrib->pkt_rpt_type == NORMAL_RX) { /* Normal rx packet */
+ if (pattrib->physt)
+ update_recvframe_phyinfo(precvframe, (struct phy_stat *)ptr);
+
+ rtw_recv_entry(precvframe);
+ } else if (pattrib->pkt_rpt_type == C2H_PACKET) {
+ struct c2h_evt_hdr_t C2hEvent;
+
+ u16 len_c2h = pattrib->pkt_len;
+ u8 *pbuf_c2h = precvframe->u.hdr.rx_data;
+ u8 *pdata_c2h;
+
+ C2hEvent.CmdID = pbuf_c2h[0];
+ C2hEvent.CmdSeq = pbuf_c2h[1];
+ C2hEvent.CmdLen = (len_c2h-2);
+ pdata_c2h = pbuf_c2h+2;
+
+ if (C2hEvent.CmdID == C2H_CCX_TX_RPT)
+ CCX_FwC2HTxRpt_8723b(padapter, pdata_c2h, C2hEvent.CmdLen);
+ else
+ rtl8723bs_c2h_packet_handler(padapter, precvframe->u.hdr.rx_data, pattrib->pkt_len);
+
+ rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
+ }
+ }
+
+ pkt_offset = round_up(pkt_offset, 8);
+ precvbuf->pdata += pkt_offset;
+ ptr = precvbuf->pdata;
+ precvframe = NULL;
+ pkt_copy = NULL;
+ }
+
+ rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
+ } while (1);
+}
+
+/*
+ * Initialize recv private variable for hardware dependent
+ * 1. recv buf
+ * 2. recv tasklet
+ *
+ */
+s32 rtl8723bs_init_recv_priv(struct adapter *padapter)
+{
+ s32 res;
+ u32 i, n;
+ struct recv_priv *precvpriv;
+ struct recv_buf *precvbuf;
+
+ res = _SUCCESS;
+ precvpriv = &padapter->recvpriv;
+
+ /* 3 1. init recv buffer */
+ INIT_LIST_HEAD(&precvpriv->free_recv_buf_queue.queue);
+ spin_lock_init(&precvpriv->free_recv_buf_queue.lock);
+ INIT_LIST_HEAD(&precvpriv->recv_buf_pending_queue.queue);
+ spin_lock_init(&precvpriv->recv_buf_pending_queue.lock);
+
+ n = NR_RECVBUFF * sizeof(struct recv_buf) + 4;
+ precvpriv->pallocated_recv_buf = rtw_zmalloc(n);
+ if (!precvpriv->pallocated_recv_buf) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ precvpriv->precv_buf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(precvpriv->pallocated_recv_buf), 4);
+
+ /* init each recv buffer */
+ precvbuf = (struct recv_buf *)precvpriv->precv_buf;
+ for (i = 0; i < NR_RECVBUFF; i++) {
+ initrecvbuf(precvbuf, padapter);
+
+ if (!precvbuf->pskb) {
+ SIZE_PTR tmpaddr = 0;
+ SIZE_PTR alignment = 0;
+
+ precvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
+
+ if (precvbuf->pskb) {
+ precvbuf->pskb->dev = padapter->pnetdev;
+
+ tmpaddr = (SIZE_PTR)precvbuf->pskb->data;
+ alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
+ skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
+ }
+ }
+
+ list_add_tail(&precvbuf->list, &precvpriv->free_recv_buf_queue.queue);
+
+ precvbuf++;
+ }
+ precvpriv->free_recv_buf_queue_cnt = i;
+
+ if (res == _FAIL)
+ goto initbuferror;
+
+ /* 3 2. init tasklet */
+ tasklet_setup(&precvpriv->recv_tasklet, rtl8723bs_recv_tasklet);
+
+ goto exit;
+
+initbuferror:
+ precvbuf = (struct recv_buf *)precvpriv->precv_buf;
+ if (precvbuf) {
+ n = precvpriv->free_recv_buf_queue_cnt;
+ precvpriv->free_recv_buf_queue_cnt = 0;
+ for (i = 0; i < n ; i++) {
+ list_del_init(&precvbuf->list);
+ rtw_os_recvbuf_resource_free(padapter, precvbuf);
+ precvbuf++;
+ }
+ precvpriv->precv_buf = NULL;
+ }
+
+ kfree(precvpriv->pallocated_recv_buf);
+ precvpriv->pallocated_recv_buf = NULL;
+
+exit:
+ return res;
+}
+
+/*
+ * Free recv private variable of hardware dependent
+ * 1. recv buf
+ * 2. recv tasklet
+ *
+ */
+void rtl8723bs_free_recv_priv(struct adapter *padapter)
+{
+ u32 i;
+ struct recv_priv *precvpriv;
+ struct recv_buf *precvbuf;
+
+ precvpriv = &padapter->recvpriv;
+
+ /* 3 1. kill tasklet */
+ tasklet_kill(&precvpriv->recv_tasklet);
+
+ /* 3 2. free all recv buffers */
+ precvbuf = (struct recv_buf *)precvpriv->precv_buf;
+ if (precvbuf) {
+ precvpriv->free_recv_buf_queue_cnt = 0;
+ for (i = 0; i < NR_RECVBUFF; i++) {
+ list_del_init(&precvbuf->list);
+ rtw_os_recvbuf_resource_free(padapter, precvbuf);
+ precvbuf++;
+ }
+ precvpriv->precv_buf = NULL;
+ }
+
+ kfree(precvpriv->pallocated_recv_buf);
+ precvpriv->pallocated_recv_buf = NULL;
+}
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c b/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c
new file mode 100644
index 000000000..15810438a
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c
@@ -0,0 +1,594 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include <drv_types.h>
+#include <rtw_debug.h>
+#include <rtl8723b_hal.h>
+
+static u8 rtw_sdio_wait_enough_TxOQT_space(struct adapter *padapter, u8 agg_num)
+{
+ u32 n = 0;
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+
+ while (pHalData->SdioTxOQTFreeSpace < agg_num) {
+ if (
+ (padapter->bSurpriseRemoved) ||
+ (padapter->bDriverStopped)
+ )
+ return false;
+
+ HalQueryTxOQTBufferStatus8723BSdio(padapter);
+
+ if ((++n % 60) == 0) {
+ msleep(1);
+ /* yield(); */
+ }
+ }
+
+ pHalData->SdioTxOQTFreeSpace -= agg_num;
+
+ return true;
+}
+
+static s32 rtl8723_dequeue_writeport(struct adapter *padapter)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
+ struct xmit_buf *pxmitbuf;
+ struct adapter *pri_padapter = padapter;
+ s32 ret = 0;
+ u8 PageIdx = 0;
+ u32 deviceId;
+ u8 bUpdatePageNum = false;
+
+ ret = ret || check_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
+
+ if (ret)
+ pxmitbuf = dequeue_pending_xmitbuf_under_survey(pxmitpriv);
+ else
+ pxmitbuf = dequeue_pending_xmitbuf(pxmitpriv);
+
+ if (!pxmitbuf)
+ return true;
+
+ deviceId = ffaddr2deviceId(pdvobjpriv, pxmitbuf->ff_hwaddr);
+
+ /* translate fifo addr to queue index */
+ switch (deviceId) {
+ case WLAN_TX_HIQ_DEVICE_ID:
+ PageIdx = HI_QUEUE_IDX;
+ break;
+
+ case WLAN_TX_MIQ_DEVICE_ID:
+ PageIdx = MID_QUEUE_IDX;
+ break;
+
+ case WLAN_TX_LOQ_DEVICE_ID:
+ PageIdx = LOW_QUEUE_IDX;
+ break;
+ }
+
+query_free_page:
+ /* check if hardware tx fifo page is enough */
+ if (!rtw_hal_sdio_query_tx_freepage(pri_padapter, PageIdx, pxmitbuf->pg_num)) {
+ if (!bUpdatePageNum) {
+ /* Total number of page is NOT available, so update current FIFO status */
+ HalQueryTxBufferStatus8723BSdio(padapter);
+ bUpdatePageNum = true;
+ goto query_free_page;
+ } else {
+ bUpdatePageNum = false;
+ enqueue_pending_xmitbuf_to_head(pxmitpriv, pxmitbuf);
+ return true;
+ }
+ }
+
+ if (
+ (padapter->bSurpriseRemoved) ||
+ (padapter->bDriverStopped)
+ )
+ goto free_xmitbuf;
+
+ if (rtw_sdio_wait_enough_TxOQT_space(padapter, pxmitbuf->agg_num) == false)
+ goto free_xmitbuf;
+
+ traffic_check_for_leave_lps(padapter, true, pxmitbuf->agg_num);
+
+ rtw_write_port(padapter, deviceId, pxmitbuf->len, (u8 *)pxmitbuf);
+
+ rtw_hal_sdio_update_tx_freepage(pri_padapter, PageIdx, pxmitbuf->pg_num);
+
+free_xmitbuf:
+ /* rtw_free_xmitframe(pxmitpriv, pframe); */
+ /* pxmitbuf->priv_data = NULL; */
+ rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
+
+ return _FAIL;
+}
+
+/*
+ * Description
+ *Transmit xmitbuf to hardware tx fifo
+ *
+ * Return
+ *_SUCCESS ok
+ *_FAIL something error
+ */
+s32 rtl8723bs_xmit_buf_handler(struct adapter *padapter)
+{
+ struct xmit_priv *pxmitpriv;
+ u8 queue_empty, queue_pending;
+ s32 ret;
+
+
+ pxmitpriv = &padapter->xmitpriv;
+
+ if (wait_for_completion_interruptible(&pxmitpriv->xmit_comp)) {
+ netdev_emerg(padapter->pnetdev,
+ "%s: down SdioXmitBufSema fail!\n", __func__);
+ return _FAIL;
+ }
+
+ ret = (padapter->bDriverStopped) || (padapter->bSurpriseRemoved);
+ if (ret)
+ return _FAIL;
+
+ queue_pending = check_pending_xmitbuf(pxmitpriv);
+
+ if (!queue_pending)
+ return _SUCCESS;
+
+ ret = rtw_register_tx_alive(padapter);
+ if (ret != _SUCCESS) {
+ return _SUCCESS;
+ }
+
+ do {
+ queue_empty = rtl8723_dequeue_writeport(padapter);
+/* dump secondary adapter xmitbuf */
+ } while (!queue_empty);
+
+ rtw_unregister_tx_alive(padapter);
+
+ return _SUCCESS;
+}
+
+/*
+ * Description:
+ *Aggregation packets and send to hardware
+ *
+ * Return:
+ *0 Success
+ *-1 Hardware resource(TX FIFO) not ready
+ *-2 Software resource(xmitbuf) not ready
+ */
+static s32 xmit_xmitframes(struct adapter *padapter, struct xmit_priv *pxmitpriv)
+{
+ s32 err, ret;
+ u32 k = 0;
+ struct hw_xmit *hwxmits, *phwxmit;
+ u8 idx, hwentry;
+ struct tx_servq *ptxservq;
+ struct list_head *sta_plist, *sta_phead, *frame_plist, *frame_phead, *tmp;
+ struct xmit_frame *pxmitframe;
+ struct __queue *pframe_queue;
+ struct xmit_buf *pxmitbuf;
+ u32 txlen, max_xmit_len;
+ u8 txdesc_size = TXDESC_SIZE;
+ int inx[4];
+
+ err = 0;
+ hwxmits = pxmitpriv->hwxmits;
+ hwentry = pxmitpriv->hwxmit_entry;
+ ptxservq = NULL;
+ pxmitframe = NULL;
+ pframe_queue = NULL;
+ pxmitbuf = NULL;
+
+ if (padapter->registrypriv.wifi_spec == 1) {
+ for (idx = 0; idx < 4; idx++)
+ inx[idx] = pxmitpriv->wmm_para_seq[idx];
+ } else {
+ inx[0] = 0;
+ inx[1] = 1;
+ inx[2] = 2;
+ inx[3] = 3;
+ }
+
+ /* 0(VO), 1(VI), 2(BE), 3(BK) */
+ for (idx = 0; idx < hwentry; idx++) {
+ phwxmit = hwxmits + inx[idx];
+
+ if (
+ (check_pending_xmitbuf(pxmitpriv)) &&
+ (padapter->mlmepriv.LinkDetectInfo.bHigherBusyTxTraffic)
+ ) {
+ if ((phwxmit->accnt > 0) && (phwxmit->accnt < 5)) {
+ err = -2;
+ break;
+ }
+ }
+
+ max_xmit_len = rtw_hal_get_sdio_tx_max_length(padapter, inx[idx]);
+
+ spin_lock_bh(&pxmitpriv->lock);
+
+ sta_phead = get_list_head(phwxmit->sta_queue);
+ /* because stop_sta_xmit may delete sta_plist at any time */
+ /* so we should add lock here, or while loop can not exit */
+ list_for_each_safe(sta_plist, tmp, sta_phead) {
+ ptxservq = list_entry(sta_plist, struct tx_servq,
+ tx_pending);
+
+ pframe_queue = &ptxservq->sta_pending;
+
+ frame_phead = get_list_head(pframe_queue);
+
+ while (list_empty(frame_phead) == false) {
+ frame_plist = get_next(frame_phead);
+ pxmitframe = container_of(frame_plist, struct xmit_frame, list);
+
+ /* check xmit_buf size enough or not */
+ txlen = txdesc_size + rtw_wlan_pkt_size(pxmitframe);
+ if (!pxmitbuf ||
+ ((_RND(pxmitbuf->len, 8) + txlen) > max_xmit_len) ||
+ (k >= (rtw_hal_sdio_max_txoqt_free_space(padapter) - 1))
+ ) {
+ if (pxmitbuf) {
+ /* pxmitbuf->priv_data will be NULL, and will crash here */
+ if (pxmitbuf->len > 0 &&
+ pxmitbuf->priv_data) {
+ struct xmit_frame *pframe;
+ pframe = (struct xmit_frame *)pxmitbuf->priv_data;
+ pframe->agg_num = k;
+ pxmitbuf->agg_num = k;
+ rtl8723b_update_txdesc(pframe, pframe->buf_addr);
+ rtw_free_xmitframe(pxmitpriv, pframe);
+ pxmitbuf->priv_data = NULL;
+ enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
+ /* can not yield under lock */
+ /* yield(); */
+ } else
+ rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
+ }
+
+ pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
+ if (!pxmitbuf) {
+#ifdef DBG_XMIT_BUF
+ netdev_err(padapter->pnetdev,
+ "%s: xmit_buf is not enough!\n",
+ __func__);
+#endif
+ err = -2;
+ complete(&(pxmitpriv->xmit_comp));
+ break;
+ }
+ k = 0;
+ }
+
+ /* ok to send, remove frame from queue */
+ if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true)
+ if (
+ (pxmitframe->attrib.psta->state & WIFI_SLEEP_STATE) &&
+ (pxmitframe->attrib.triggered == 0)
+ )
+ break;
+
+ list_del_init(&pxmitframe->list);
+ ptxservq->qcnt--;
+ phwxmit->accnt--;
+
+ if (k == 0) {
+ pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
+ pxmitbuf->priv_data = (u8 *)pxmitframe;
+ }
+
+ /* coalesce the xmitframe to xmitbuf */
+ pxmitframe->pxmitbuf = pxmitbuf;
+ pxmitframe->buf_addr = pxmitbuf->ptail;
+
+ ret = rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);
+ if (ret == _FAIL) {
+ netdev_err(padapter->pnetdev,
+ "%s: coalesce FAIL!",
+ __func__);
+ /* Todo: error handler */
+ } else {
+ k++;
+ if (k != 1)
+ rtl8723b_update_txdesc(pxmitframe, pxmitframe->buf_addr);
+ rtw_count_tx_stats(padapter, pxmitframe, pxmitframe->attrib.last_txcmdsz);
+
+ txlen = txdesc_size + pxmitframe->attrib.last_txcmdsz;
+ pxmitframe->pg_num = (txlen + 127) / 128;
+ pxmitbuf->pg_num += (txlen + 127) / 128;
+ pxmitbuf->ptail += _RND(txlen, 8); /* round to 8 bytes alignment */
+ pxmitbuf->len = _RND(pxmitbuf->len, 8) + txlen;
+ }
+
+ if (k != 1)
+ rtw_free_xmitframe(pxmitpriv, pxmitframe);
+ pxmitframe = NULL;
+ }
+
+ if (list_empty(&pframe_queue->queue))
+ list_del_init(&ptxservq->tx_pending);
+
+ if (err)
+ break;
+ }
+ spin_unlock_bh(&pxmitpriv->lock);
+
+ /* dump xmit_buf to hw tx fifo */
+ if (pxmitbuf) {
+ if (pxmitbuf->len > 0) {
+ struct xmit_frame *pframe;
+ pframe = (struct xmit_frame *)pxmitbuf->priv_data;
+ pframe->agg_num = k;
+ pxmitbuf->agg_num = k;
+ rtl8723b_update_txdesc(pframe, pframe->buf_addr);
+ rtw_free_xmitframe(pxmitpriv, pframe);
+ pxmitbuf->priv_data = NULL;
+ enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
+ yield();
+ } else
+ rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
+ pxmitbuf = NULL;
+ }
+
+ if (err)
+ break;
+ }
+
+ return err;
+}
+
+/*
+ * Description
+ *Transmit xmitframe from queue
+ *
+ * Return
+ *_SUCCESS ok
+ *_FAIL something error
+ */
+static s32 rtl8723bs_xmit_handler(struct adapter *padapter)
+{
+ struct xmit_priv *pxmitpriv;
+ s32 ret;
+
+
+ pxmitpriv = &padapter->xmitpriv;
+
+ if (wait_for_completion_interruptible(&pxmitpriv->SdioXmitStart)) {
+ netdev_emerg(padapter->pnetdev, "%s: SdioXmitStart fail!\n",
+ __func__);
+ return _FAIL;
+ }
+
+next:
+ if (
+ (padapter->bDriverStopped) ||
+ (padapter->bSurpriseRemoved)
+ )
+ return _FAIL;
+
+ spin_lock_bh(&pxmitpriv->lock);
+ ret = rtw_txframes_pending(padapter);
+ spin_unlock_bh(&pxmitpriv->lock);
+ if (ret == 0) {
+ return _SUCCESS;
+ }
+
+ /* dequeue frame and write to hardware */
+
+ ret = xmit_xmitframes(padapter, pxmitpriv);
+ if (ret == -2) {
+ /* here sleep 1ms will cause big TP loss of TX */
+ /* from 50+ to 40+ */
+ if (padapter->registrypriv.wifi_spec)
+ msleep(1);
+ else
+ yield();
+ goto next;
+ }
+
+ spin_lock_bh(&pxmitpriv->lock);
+ ret = rtw_txframes_pending(padapter);
+ spin_unlock_bh(&pxmitpriv->lock);
+ if (ret == 1) {
+ goto next;
+ }
+
+ return _SUCCESS;
+}
+
+int rtl8723bs_xmit_thread(void *context)
+{
+ s32 ret;
+ struct adapter *padapter;
+ struct xmit_priv *pxmitpriv;
+ u8 thread_name[20];
+
+ ret = _SUCCESS;
+ padapter = context;
+ pxmitpriv = &padapter->xmitpriv;
+
+ rtw_sprintf(thread_name, 20, "RTWHALXT-%s", ADPT_ARG(padapter));
+ thread_enter(thread_name);
+
+ do {
+ ret = rtl8723bs_xmit_handler(padapter);
+ if (signal_pending(current)) {
+ flush_signals(current);
+ }
+ } while (_SUCCESS == ret);
+
+ complete(&pxmitpriv->SdioXmitTerminate);
+
+ return 0;
+}
+
+s32 rtl8723bs_mgnt_xmit(
+ struct adapter *padapter, struct xmit_frame *pmgntframe
+)
+{
+ s32 ret = _SUCCESS;
+ struct pkt_attrib *pattrib;
+ struct xmit_buf *pxmitbuf;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
+ u8 *pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ u8 txdesc_size = TXDESC_SIZE;
+
+ pattrib = &pmgntframe->attrib;
+ pxmitbuf = pmgntframe->pxmitbuf;
+
+ rtl8723b_update_txdesc(pmgntframe, pmgntframe->buf_addr);
+
+ pxmitbuf->len = txdesc_size + pattrib->last_txcmdsz;
+ pxmitbuf->pg_num = (pxmitbuf->len + 127) / 128; /* 128 is tx page size */
+ pxmitbuf->ptail = pmgntframe->buf_addr + pxmitbuf->len;
+ pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pmgntframe);
+
+ rtw_count_tx_stats(padapter, pmgntframe, pattrib->last_txcmdsz);
+
+ rtw_free_xmitframe(pxmitpriv, pmgntframe);
+
+ pxmitbuf->priv_data = NULL;
+
+ if (GetFrameSubType(pframe) == WIFI_BEACON) { /* dump beacon directly */
+ ret = rtw_write_port(padapter, pdvobjpriv->Queue2Pipe[pxmitbuf->ff_hwaddr], pxmitbuf->len, (u8 *)pxmitbuf);
+ if (ret != _SUCCESS)
+ rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);
+
+ rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
+ } else
+ enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
+
+ return ret;
+}
+
+/*
+ * Description:
+ *Handle xmitframe(packet) come from rtw_xmit()
+ *
+ * Return:
+ *true dump packet directly ok
+ *false enqueue, temporary can't transmit packets to hardware
+ */
+s32 rtl8723bs_hal_xmit(
+ struct adapter *padapter, struct xmit_frame *pxmitframe
+)
+{
+ struct xmit_priv *pxmitpriv;
+ s32 err;
+
+
+ pxmitframe->attrib.qsel = pxmitframe->attrib.priority;
+ pxmitpriv = &padapter->xmitpriv;
+
+ if (
+ (pxmitframe->frame_tag == DATA_FRAMETAG) &&
+ (pxmitframe->attrib.ether_type != 0x0806) &&
+ (pxmitframe->attrib.ether_type != 0x888e) &&
+ (pxmitframe->attrib.dhcp_pkt != 1)
+ ) {
+ if (padapter->mlmepriv.LinkDetectInfo.bBusyTraffic)
+ rtw_issue_addbareq_cmd(padapter, pxmitframe);
+ }
+
+ spin_lock_bh(&pxmitpriv->lock);
+ err = rtw_xmitframe_enqueue(padapter, pxmitframe);
+ spin_unlock_bh(&pxmitpriv->lock);
+ if (err != _SUCCESS) {
+ rtw_free_xmitframe(pxmitpriv, pxmitframe);
+
+ pxmitpriv->tx_drop++;
+ return true;
+ }
+
+ complete(&pxmitpriv->SdioXmitStart);
+
+ return false;
+}
+
+s32 rtl8723bs_hal_xmitframe_enqueue(
+ struct adapter *padapter, struct xmit_frame *pxmitframe
+)
+{
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ s32 err;
+
+ err = rtw_xmitframe_enqueue(padapter, pxmitframe);
+ if (err != _SUCCESS) {
+ rtw_free_xmitframe(pxmitpriv, pxmitframe);
+
+ pxmitpriv->tx_drop++;
+ } else {
+ complete(&pxmitpriv->SdioXmitStart);
+ }
+
+ return err;
+
+}
+
+/*
+ * Return
+ *_SUCCESS start thread ok
+ *_FAIL start thread fail
+ *
+ */
+s32 rtl8723bs_init_xmit_priv(struct adapter *padapter)
+{
+ struct xmit_priv *xmitpriv = &padapter->xmitpriv;
+ struct hal_com_data *phal;
+
+
+ phal = GET_HAL_DATA(padapter);
+
+ spin_lock_init(&phal->SdioTxFIFOFreePageLock);
+ init_completion(&xmitpriv->SdioXmitStart);
+ init_completion(&xmitpriv->SdioXmitTerminate);
+
+ return _SUCCESS;
+}
+
+void rtl8723bs_free_xmit_priv(struct adapter *padapter)
+{
+ struct xmit_priv *pxmitpriv;
+ struct xmit_buf *pxmitbuf;
+ struct __queue *pqueue;
+ struct list_head *plist, *phead;
+ struct list_head tmplist;
+
+
+ pxmitpriv = &padapter->xmitpriv;
+ pqueue = &pxmitpriv->pending_xmitbuf_queue;
+ phead = get_list_head(pqueue);
+ INIT_LIST_HEAD(&tmplist);
+
+ spin_lock_bh(&pqueue->lock);
+ if (!list_empty(&pqueue->queue)) {
+ /* Insert tmplist to end of queue, and delete phead */
+ /* then tmplist become head of queue. */
+ list_add_tail(&tmplist, phead);
+ list_del_init(phead);
+ }
+ spin_unlock_bh(&pqueue->lock);
+
+ phead = &tmplist;
+ while (list_empty(phead) == false) {
+ plist = get_next(phead);
+ list_del_init(plist);
+
+ pxmitbuf = container_of(plist, struct xmit_buf, list);
+ rtw_free_xmitframe(pxmitpriv, (struct xmit_frame *)pxmitbuf->priv_data);
+ pxmitbuf->priv_data = NULL;
+ rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
+ }
+}
diff --git a/drivers/staging/rtl8723bs/hal/sdio_halinit.c b/drivers/staging/rtl8723bs/hal/sdio_halinit.c
new file mode 100644
index 000000000..c9cd6578f
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/sdio_halinit.c
@@ -0,0 +1,1301 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#include <drv_types.h>
+#include <rtw_debug.h>
+#include <rtl8723b_hal.h>
+
+#include "hal_com_h2c.h"
+/*
+ * Description:
+ *Call power on sequence to enable card
+ *
+ * Return:
+ *_SUCCESS enable success
+ *_FAIL enable fail
+ */
+static u8 CardEnable(struct adapter *padapter)
+{
+ u8 bMacPwrCtrlOn;
+ u8 ret = _FAIL;
+
+
+ rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
+ if (!bMacPwrCtrlOn) {
+ /* RSV_CTRL 0x1C[7:0] = 0x00 */
+ /* unlock ISO/CLK/Power control register */
+ rtw_write8(padapter, REG_RSV_CTRL, 0x0);
+
+ ret = HalPwrSeqCmdParsing(padapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, rtl8723B_card_enable_flow);
+ if (ret == _SUCCESS) {
+ u8 bMacPwrCtrlOn = true;
+ rtw_hal_set_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
+ }
+ } else
+ ret = _SUCCESS;
+
+ return ret;
+}
+
+static
+u8 _InitPowerOn_8723BS(struct adapter *padapter)
+{
+ u8 value8;
+ u16 value16;
+ u32 value32;
+ u8 ret;
+/* u8 bMacPwrCtrlOn; */
+
+
+ /* all of these MUST be configured before power on */
+
+ /* only cmd52 can be used before power on(card enable) */
+ ret = CardEnable(padapter);
+ if (!ret)
+ return _FAIL;
+
+ /* Radio-Off Pin Trigger */
+ value8 = rtw_read8(padapter, REG_GPIO_INTM + 1);
+ value8 |= BIT(1); /* Enable falling edge triggering interrupt */
+ rtw_write8(padapter, REG_GPIO_INTM + 1, value8);
+ value8 = rtw_read8(padapter, REG_GPIO_IO_SEL_2 + 1);
+ value8 |= BIT(1);
+ rtw_write8(padapter, REG_GPIO_IO_SEL_2 + 1, value8);
+
+ /* Enable power down and GPIO interrupt */
+ value16 = rtw_read16(padapter, REG_APS_FSMCO);
+ value16 |= EnPDN; /* Enable HW power down and RF on */
+ rtw_write16(padapter, REG_APS_FSMCO, value16);
+
+ /* Enable CMD53 R/W Operation */
+/* bMacPwrCtrlOn = true; */
+/* rtw_hal_set_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn); */
+
+ rtw_write8(padapter, REG_CR, 0x00);
+ /* Enable MAC DMA/WMAC/SCHEDULE/SEC block */
+ value16 = rtw_read16(padapter, REG_CR);
+ value16 |= (
+ HCI_TXDMA_EN |
+ HCI_RXDMA_EN |
+ TXDMA_EN |
+ RXDMA_EN |
+ PROTOCOL_EN |
+ SCHEDULE_EN |
+ ENSEC |
+ CALTMR_EN
+ );
+ rtw_write16(padapter, REG_CR, value16);
+
+ hal_btcoex_PowerOnSetting(padapter);
+
+ /* external switch to S1 */
+ /* 0x38[11] = 0x1 */
+ /* 0x4c[23] = 0x1 */
+ /* 0x64[0] = 0 */
+ value16 = rtw_read16(padapter, REG_PWR_DATA);
+ /* Switch the control of EESK, EECS to RFC for DPDT or Antenna switch */
+ value16 |= BIT(11); /* BIT_EEPRPAD_RFE_CTRL_EN */
+ rtw_write16(padapter, REG_PWR_DATA, value16);
+
+ value32 = rtw_read32(padapter, REG_LEDCFG0);
+ value32 |= BIT(23); /* DPDT_SEL_EN, 1 for SW control */
+ rtw_write32(padapter, REG_LEDCFG0, value32);
+
+ value8 = rtw_read8(padapter, REG_PAD_CTRL1_8723B);
+ value8 &= ~BIT(0); /* BIT_SW_DPDT_SEL_DATA, DPDT_SEL default configuration */
+ rtw_write8(padapter, REG_PAD_CTRL1_8723B, value8);
+
+ return _SUCCESS;
+}
+
+/* Tx Page FIFO threshold */
+static void _init_available_page_threshold(struct adapter *padapter, u8 numHQ, u8 numNQ, u8 numLQ, u8 numPubQ)
+{
+ u16 HQ_threshold, NQ_threshold, LQ_threshold;
+
+ HQ_threshold = (numPubQ + numHQ + 1) >> 1;
+ HQ_threshold |= (HQ_threshold << 8);
+
+ NQ_threshold = (numPubQ + numNQ + 1) >> 1;
+ NQ_threshold |= (NQ_threshold << 8);
+
+ LQ_threshold = (numPubQ + numLQ + 1) >> 1;
+ LQ_threshold |= (LQ_threshold << 8);
+
+ rtw_write16(padapter, 0x218, HQ_threshold);
+ rtw_write16(padapter, 0x21A, NQ_threshold);
+ rtw_write16(padapter, 0x21C, LQ_threshold);
+}
+
+static void _InitQueueReservedPage(struct adapter *padapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
+ u32 numHQ = 0;
+ u32 numLQ = 0;
+ u32 numNQ = 0;
+ u32 numPubQ;
+ u32 value32;
+ u8 value8;
+ bool bWiFiConfig = pregistrypriv->wifi_spec;
+
+ if (pHalData->OutEpQueueSel & TX_SELE_HQ)
+ numHQ = bWiFiConfig ? WMM_NORMAL_PAGE_NUM_HPQ_8723B : NORMAL_PAGE_NUM_HPQ_8723B;
+
+ if (pHalData->OutEpQueueSel & TX_SELE_LQ)
+ numLQ = bWiFiConfig ? WMM_NORMAL_PAGE_NUM_LPQ_8723B : NORMAL_PAGE_NUM_LPQ_8723B;
+
+ /* NOTE: This step shall be proceed before writing REG_RQPN. */
+ if (pHalData->OutEpQueueSel & TX_SELE_NQ)
+ numNQ = bWiFiConfig ? WMM_NORMAL_PAGE_NUM_NPQ_8723B : NORMAL_PAGE_NUM_NPQ_8723B;
+
+ numPubQ = TX_TOTAL_PAGE_NUMBER_8723B - numHQ - numLQ - numNQ;
+
+ value8 = (u8)_NPQ(numNQ);
+ rtw_write8(padapter, REG_RQPN_NPQ, value8);
+
+ /* TX DMA */
+ value32 = _HPQ(numHQ) | _LPQ(numLQ) | _PUBQ(numPubQ) | LD_RQPN;
+ rtw_write32(padapter, REG_RQPN, value32);
+
+ rtw_hal_set_sdio_tx_max_length(padapter, numHQ, numNQ, numLQ, numPubQ);
+
+ _init_available_page_threshold(padapter, numHQ, numNQ, numLQ, numPubQ);
+}
+
+static void _InitTxBufferBoundary(struct adapter *padapter)
+{
+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
+
+ /* u16 txdmactrl; */
+ u8 txpktbuf_bndy;
+
+ if (!pregistrypriv->wifi_spec) {
+ txpktbuf_bndy = TX_PAGE_BOUNDARY_8723B;
+ } else {
+ /* for WMM */
+ txpktbuf_bndy = WMM_NORMAL_TX_PAGE_BOUNDARY_8723B;
+ }
+
+ rtw_write8(padapter, REG_TXPKTBUF_BCNQ_BDNY_8723B, txpktbuf_bndy);
+ rtw_write8(padapter, REG_TXPKTBUF_MGQ_BDNY_8723B, txpktbuf_bndy);
+ rtw_write8(padapter, REG_TXPKTBUF_WMAC_LBK_BF_HD_8723B, txpktbuf_bndy);
+ rtw_write8(padapter, REG_TRXFF_BNDY, txpktbuf_bndy);
+ rtw_write8(padapter, REG_TDECTRL + 1, txpktbuf_bndy);
+}
+
+static void _InitNormalChipRegPriority(
+ struct adapter *Adapter,
+ u16 beQ,
+ u16 bkQ,
+ u16 viQ,
+ u16 voQ,
+ u16 mgtQ,
+ u16 hiQ
+)
+{
+ u16 value16 = (rtw_read16(Adapter, REG_TRXDMA_CTRL) & 0x7);
+
+ value16 |=
+ _TXDMA_BEQ_MAP(beQ) |
+ _TXDMA_BKQ_MAP(bkQ) |
+ _TXDMA_VIQ_MAP(viQ) |
+ _TXDMA_VOQ_MAP(voQ) |
+ _TXDMA_MGQ_MAP(mgtQ) |
+ _TXDMA_HIQ_MAP(hiQ);
+
+ rtw_write16(Adapter, REG_TRXDMA_CTRL, value16);
+}
+
+static void _InitNormalChipOneOutEpPriority(struct adapter *Adapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+
+ u16 value = 0;
+ switch (pHalData->OutEpQueueSel) {
+ case TX_SELE_HQ:
+ value = QUEUE_HIGH;
+ break;
+ case TX_SELE_LQ:
+ value = QUEUE_LOW;
+ break;
+ case TX_SELE_NQ:
+ value = QUEUE_NORMAL;
+ break;
+ default:
+ break;
+ }
+
+ _InitNormalChipRegPriority(
+ Adapter, value, value, value, value, value, value
+ );
+
+}
+
+static void _InitNormalChipTwoOutEpPriority(struct adapter *Adapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+ struct registry_priv *pregistrypriv = &Adapter->registrypriv;
+ u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ;
+
+
+ u16 valueHi = 0;
+ u16 valueLow = 0;
+
+ switch (pHalData->OutEpQueueSel) {
+ case (TX_SELE_HQ | TX_SELE_LQ):
+ valueHi = QUEUE_HIGH;
+ valueLow = QUEUE_LOW;
+ break;
+ case (TX_SELE_NQ | TX_SELE_LQ):
+ valueHi = QUEUE_NORMAL;
+ valueLow = QUEUE_LOW;
+ break;
+ case (TX_SELE_HQ | TX_SELE_NQ):
+ valueHi = QUEUE_HIGH;
+ valueLow = QUEUE_NORMAL;
+ break;
+ default:
+ break;
+ }
+
+ if (!pregistrypriv->wifi_spec) {
+ beQ = valueLow;
+ bkQ = valueLow;
+ viQ = valueHi;
+ voQ = valueHi;
+ mgtQ = valueHi;
+ hiQ = valueHi;
+ } else {
+ /* for WMM , CONFIG_OUT_EP_WIFI_MODE */
+ beQ = valueLow;
+ bkQ = valueHi;
+ viQ = valueHi;
+ voQ = valueLow;
+ mgtQ = valueHi;
+ hiQ = valueHi;
+ }
+
+ _InitNormalChipRegPriority(Adapter, beQ, bkQ, viQ, voQ, mgtQ, hiQ);
+
+}
+
+static void _InitNormalChipThreeOutEpPriority(struct adapter *padapter)
+{
+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
+ u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ;
+
+ if (!pregistrypriv->wifi_spec) {
+ /* typical setting */
+ beQ = QUEUE_LOW;
+ bkQ = QUEUE_LOW;
+ viQ = QUEUE_NORMAL;
+ voQ = QUEUE_HIGH;
+ mgtQ = QUEUE_HIGH;
+ hiQ = QUEUE_HIGH;
+ } else {
+ /* for WMM */
+ beQ = QUEUE_LOW;
+ bkQ = QUEUE_NORMAL;
+ viQ = QUEUE_NORMAL;
+ voQ = QUEUE_HIGH;
+ mgtQ = QUEUE_HIGH;
+ hiQ = QUEUE_HIGH;
+ }
+ _InitNormalChipRegPriority(padapter, beQ, bkQ, viQ, voQ, mgtQ, hiQ);
+}
+
+static void _InitQueuePriority(struct adapter *Adapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+
+ switch (pHalData->OutEpNumber) {
+ case 1:
+ _InitNormalChipOneOutEpPriority(Adapter);
+ break;
+ case 2:
+ _InitNormalChipTwoOutEpPriority(Adapter);
+ break;
+ case 3:
+ _InitNormalChipThreeOutEpPriority(Adapter);
+ break;
+ default:
+ break;
+ }
+
+
+}
+
+static void _InitPageBoundary(struct adapter *padapter)
+{
+ /* RX Page Boundary */
+ u16 rxff_bndy = RX_DMA_BOUNDARY_8723B;
+
+ rtw_write16(padapter, (REG_TRXFF_BNDY + 2), rxff_bndy);
+}
+
+static void _InitTransferPageSize(struct adapter *padapter)
+{
+ /* Tx page size is always 128. */
+
+ u8 value8;
+ value8 = _PSRX(PBP_128) | _PSTX(PBP_128);
+ rtw_write8(padapter, REG_PBP, value8);
+}
+
+static void _InitDriverInfoSize(struct adapter *padapter, u8 drvInfoSize)
+{
+ rtw_write8(padapter, REG_RX_DRVINFO_SZ, drvInfoSize);
+}
+
+static void _InitNetworkType(struct adapter *padapter)
+{
+ u32 value32;
+
+ value32 = rtw_read32(padapter, REG_CR);
+
+ /* TODO: use the other function to set network type */
+/* value32 = (value32 & ~MASK_NETTYPE) | _NETTYPE(NT_LINK_AD_HOC); */
+ value32 = (value32 & ~MASK_NETTYPE) | _NETTYPE(NT_LINK_AP);
+
+ rtw_write32(padapter, REG_CR, value32);
+}
+
+static void _InitWMACSetting(struct adapter *padapter)
+{
+ struct hal_com_data *pHalData;
+ u16 value16;
+
+
+ pHalData = GET_HAL_DATA(padapter);
+
+ pHalData->ReceiveConfig = 0;
+ pHalData->ReceiveConfig |= RCR_APM | RCR_AM | RCR_AB;
+ pHalData->ReceiveConfig |= RCR_CBSSID_DATA | RCR_CBSSID_BCN | RCR_AMF;
+ pHalData->ReceiveConfig |= RCR_HTC_LOC_CTRL;
+ pHalData->ReceiveConfig |= RCR_APP_PHYST_RXFF | RCR_APP_ICV | RCR_APP_MIC;
+ rtw_write32(padapter, REG_RCR, pHalData->ReceiveConfig);
+
+ /* Accept all multicast address */
+ rtw_write32(padapter, REG_MAR, 0xFFFFFFFF);
+ rtw_write32(padapter, REG_MAR + 4, 0xFFFFFFFF);
+
+ /* Accept all data frames */
+ value16 = 0xFFFF;
+ rtw_write16(padapter, REG_RXFLTMAP2, value16);
+
+ /* 2010.09.08 hpfan */
+ /* Since ADF is removed from RCR, ps-poll will not be indicate to driver, */
+ /* RxFilterMap should mask ps-poll to gurantee AP mode can rx ps-poll. */
+ value16 = 0x400;
+ rtw_write16(padapter, REG_RXFLTMAP1, value16);
+
+ /* Accept all management frames */
+ value16 = 0xFFFF;
+ rtw_write16(padapter, REG_RXFLTMAP0, value16);
+}
+
+static void _InitAdaptiveCtrl(struct adapter *padapter)
+{
+ u16 value16;
+ u32 value32;
+
+ /* Response Rate Set */
+ value32 = rtw_read32(padapter, REG_RRSR);
+ value32 &= ~RATE_BITMAP_ALL;
+ value32 |= RATE_RRSR_CCK_ONLY_1M;
+ rtw_write32(padapter, REG_RRSR, value32);
+
+ /* CF-END Threshold */
+ /* m_spIoBase->rtw_write8(REG_CFEND_TH, 0x1); */
+
+ /* SIFS (used in NAV) */
+ value16 = _SPEC_SIFS_CCK(0x10) | _SPEC_SIFS_OFDM(0x10);
+ rtw_write16(padapter, REG_SPEC_SIFS, value16);
+
+ /* Retry Limit */
+ value16 = _LRL(0x30) | _SRL(0x30);
+ rtw_write16(padapter, REG_RL, value16);
+}
+
+static void _InitEDCA(struct adapter *padapter)
+{
+ /* Set Spec SIFS (used in NAV) */
+ rtw_write16(padapter, REG_SPEC_SIFS, 0x100a);
+ rtw_write16(padapter, REG_MAC_SPEC_SIFS, 0x100a);
+
+ /* Set SIFS for CCK */
+ rtw_write16(padapter, REG_SIFS_CTX, 0x100a);
+
+ /* Set SIFS for OFDM */
+ rtw_write16(padapter, REG_SIFS_TRX, 0x100a);
+
+ /* TXOP */
+ rtw_write32(padapter, REG_EDCA_BE_PARAM, 0x005EA42B);
+ rtw_write32(padapter, REG_EDCA_BK_PARAM, 0x0000A44F);
+ rtw_write32(padapter, REG_EDCA_VI_PARAM, 0x005EA324);
+ rtw_write32(padapter, REG_EDCA_VO_PARAM, 0x002FA226);
+}
+
+static void _InitRetryFunction(struct adapter *padapter)
+{
+ u8 value8;
+
+ value8 = rtw_read8(padapter, REG_FWHW_TXQ_CTRL);
+ value8 |= EN_AMPDU_RTY_NEW;
+ rtw_write8(padapter, REG_FWHW_TXQ_CTRL, value8);
+
+ /* Set ACK timeout */
+ rtw_write8(padapter, REG_ACKTO, 0x40);
+}
+
+static void HalRxAggr8723BSdio(struct adapter *padapter)
+{
+ u8 valueDMATimeout;
+ u8 valueDMAPageCount;
+
+ valueDMATimeout = 0x06;
+ valueDMAPageCount = 0x06;
+
+ rtw_write8(padapter, REG_RXDMA_AGG_PG_TH + 1, valueDMATimeout);
+ rtw_write8(padapter, REG_RXDMA_AGG_PG_TH, valueDMAPageCount);
+}
+
+static void sdio_AggSettingRxUpdate(struct adapter *padapter)
+{
+ u8 valueDMA;
+ u8 valueRxAggCtrl = 0;
+ u8 aggBurstNum = 3; /* 0:1, 1:2, 2:3, 3:4 */
+ u8 aggBurstSize = 0; /* 0:1K, 1:512Byte, 2:256Byte... */
+
+ valueDMA = rtw_read8(padapter, REG_TRXDMA_CTRL);
+ valueDMA |= RXDMA_AGG_EN;
+ rtw_write8(padapter, REG_TRXDMA_CTRL, valueDMA);
+
+ valueRxAggCtrl |= RXDMA_AGG_MODE_EN;
+ valueRxAggCtrl |= ((aggBurstNum << 2) & 0x0C);
+ valueRxAggCtrl |= ((aggBurstSize << 4) & 0x30);
+ rtw_write8(padapter, REG_RXDMA_MODE_CTRL_8723B, valueRxAggCtrl);/* RxAggLowThresh = 4*1K */
+}
+
+static void _initSdioAggregationSetting(struct adapter *padapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+
+ /* Tx aggregation setting */
+/* sdio_AggSettingTxUpdate(padapter); */
+
+ /* Rx aggregation setting */
+ HalRxAggr8723BSdio(padapter);
+
+ sdio_AggSettingRxUpdate(padapter);
+
+ /* 201/12/10 MH Add for USB agg mode dynamic switch. */
+ pHalData->UsbRxHighSpeedMode = false;
+}
+
+static void _InitOperationMode(struct adapter *padapter)
+{
+ struct mlme_ext_priv *pmlmeext;
+ u8 regBwOpMode = 0;
+
+ pmlmeext = &padapter->mlmeextpriv;
+
+ /* 1 This part need to modified according to the rate set we filtered!! */
+ /* */
+ /* Set RRSR, RATR, and REG_BWOPMODE registers */
+ /* */
+ switch (pmlmeext->cur_wireless_mode) {
+ case WIRELESS_MODE_B:
+ regBwOpMode = BW_OPMODE_20MHZ;
+ break;
+ case WIRELESS_MODE_G:
+ regBwOpMode = BW_OPMODE_20MHZ;
+ break;
+ case WIRELESS_MODE_AUTO:
+ regBwOpMode = BW_OPMODE_20MHZ;
+ break;
+ case WIRELESS_MODE_N_24G:
+ /* It support CCK rate by default. */
+ /* CCK rate will be filtered out only when associated AP does not support it. */
+ regBwOpMode = BW_OPMODE_20MHZ;
+ break;
+
+ default: /* for MacOSX compiler warning. */
+ break;
+ }
+
+ rtw_write8(padapter, REG_BWOPMODE, regBwOpMode);
+
+}
+
+static void _InitInterrupt(struct adapter *padapter)
+{
+ /* HISR - turn all off */
+ rtw_write32(padapter, REG_HISR, 0);
+
+ /* HIMR - turn all off */
+ rtw_write32(padapter, REG_HIMR, 0);
+
+ /* */
+ /* Initialize and enable SDIO Host Interrupt. */
+ /* */
+ InitInterrupt8723BSdio(padapter);
+
+ /* */
+ /* Initialize system Host Interrupt. */
+ /* */
+ InitSysInterrupt8723BSdio(padapter);
+}
+
+static void _InitRFType(struct adapter *padapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+
+ pHalData->rf_chip = RF_6052;
+}
+
+static void _RfPowerSave(struct adapter *padapter)
+{
+/* YJ, TODO */
+}
+
+/* */
+/* 2010/08/09 MH Add for power down check. */
+/* */
+static bool HalDetectPwrDownMode(struct adapter *Adapter)
+{
+ u8 tmpvalue;
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+ struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(Adapter);
+
+
+ EFUSE_ShadowRead(Adapter, 1, 0x7B/*EEPROM_RF_OPT3_92C*/, (u32 *)&tmpvalue);
+
+ /* 2010/08/25 MH INF priority > PDN Efuse value. */
+ if (tmpvalue & BIT4 && pwrctrlpriv->reg_pdnmode)
+ pHalData->pwrdown = true;
+ else
+ pHalData->pwrdown = false;
+
+ return pHalData->pwrdown;
+} /* HalDetectPwrDownMode */
+
+static u32 rtl8723bs_hal_init(struct adapter *padapter)
+{
+ s32 ret;
+ struct hal_com_data *pHalData;
+ struct pwrctrl_priv *pwrctrlpriv;
+ u32 NavUpper = WiFiNavUpperUs;
+ u8 u1bTmp;
+
+ pHalData = GET_HAL_DATA(padapter);
+ pwrctrlpriv = adapter_to_pwrctl(padapter);
+
+ if (
+ adapter_to_pwrctl(padapter)->bips_processing == true &&
+ adapter_to_pwrctl(padapter)->pre_ips_type == 0
+ ) {
+ unsigned long start_time;
+ u8 cpwm_orig, cpwm_now;
+ u8 val8, bMacPwrCtrlOn = true;
+
+ /* for polling cpwm */
+ cpwm_orig = 0;
+ rtw_hal_get_hwreg(padapter, HW_VAR_CPWM, &cpwm_orig);
+
+ /* ser rpwm */
+ val8 = rtw_read8(padapter, SDIO_LOCAL_BASE | SDIO_REG_HRPWM1);
+ val8 &= 0x80;
+ val8 += 0x80;
+ val8 |= BIT(6);
+ rtw_write8(padapter, SDIO_LOCAL_BASE | SDIO_REG_HRPWM1, val8);
+ adapter_to_pwrctl(padapter)->tog = (val8 + 0x80) & 0x80;
+
+ /* do polling cpwm */
+ start_time = jiffies;
+ do {
+
+ mdelay(1);
+
+ rtw_hal_get_hwreg(padapter, HW_VAR_CPWM, &cpwm_now);
+ if ((cpwm_orig ^ cpwm_now) & 0x80)
+ break;
+
+ if (jiffies_to_msecs(jiffies - start_time) > 100)
+ break;
+
+ } while (1);
+
+ rtl8723b_set_FwPwrModeInIPS_cmd(padapter, 0);
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
+
+ hal_btcoex_InitHwConfig(padapter, false);
+
+ return _SUCCESS;
+ }
+
+ /* Disable Interrupt first. */
+/* rtw_hal_disable_interrupt(padapter); */
+
+ ret = _InitPowerOn_8723BS(padapter);
+ if (ret == _FAIL)
+ return _FAIL;
+
+ rtw_write8(padapter, REG_EARLY_MODE_CONTROL, 0);
+
+ ret = rtl8723b_FirmwareDownload(padapter, false);
+ if (ret != _SUCCESS) {
+ padapter->bFWReady = false;
+ pHalData->fw_ractrl = false;
+ return ret;
+ } else {
+ padapter->bFWReady = true;
+ pHalData->fw_ractrl = true;
+ }
+
+ rtl8723b_InitializeFirmwareVars(padapter);
+
+/* SIC_Init(padapter); */
+
+ if (pwrctrlpriv->reg_rfoff)
+ pwrctrlpriv->rf_pwrstate = rf_off;
+
+ /* 2010/08/09 MH We need to check if we need to turnon or off RF after detecting */
+ /* HW GPIO pin. Before PHY_RFConfig8192C. */
+ HalDetectPwrDownMode(padapter);
+
+ /* Set RF type for BB/RF configuration */
+ _InitRFType(padapter);
+
+ /* Save target channel */
+ /* <Roger_Notes> Current Channel will be updated again later. */
+ pHalData->CurrentChannel = 6;
+
+ ret = PHY_MACConfig8723B(padapter);
+ if (ret != _SUCCESS)
+ return ret;
+ /* */
+ /* d. Initialize BB related configurations. */
+ /* */
+ ret = PHY_BBConfig8723B(padapter);
+ if (ret != _SUCCESS)
+ return ret;
+
+ /* If RF is on, we need to init RF. Otherwise, skip the procedure. */
+ /* We need to follow SU method to change the RF cfg.txt. Default disable RF TX/RX mode. */
+ /* if (pHalData->eRFPowerState == eRfOn) */
+ {
+ ret = PHY_RFConfig8723B(padapter);
+ if (ret != _SUCCESS)
+ return ret;
+ }
+
+ /* */
+ /* Joseph Note: Keep RfRegChnlVal for later use. */
+ /* */
+ pHalData->RfRegChnlVal[0] =
+ PHY_QueryRFReg(padapter, (enum rf_path)0, RF_CHNLBW, bRFRegOffsetMask);
+ pHalData->RfRegChnlVal[1] =
+ PHY_QueryRFReg(padapter, (enum rf_path)1, RF_CHNLBW, bRFRegOffsetMask);
+
+
+ /* if (!pHalData->bMACFuncEnable) { */
+ _InitQueueReservedPage(padapter);
+ _InitTxBufferBoundary(padapter);
+
+ /* init LLT after tx buffer boundary is defined */
+ ret = rtl8723b_InitLLTTable(padapter);
+ if (ret != _SUCCESS)
+ return _FAIL;
+
+ /* */
+ _InitQueuePriority(padapter);
+ _InitPageBoundary(padapter);
+ _InitTransferPageSize(padapter);
+
+ /* Get Rx PHY status in order to report RSSI and others. */
+ _InitDriverInfoSize(padapter, DRVINFO_SZ);
+ hal_init_macaddr(padapter);
+ _InitNetworkType(padapter);
+ _InitWMACSetting(padapter);
+ _InitAdaptiveCtrl(padapter);
+ _InitEDCA(padapter);
+ _InitRetryFunction(padapter);
+ _initSdioAggregationSetting(padapter);
+ _InitOperationMode(padapter);
+ rtl8723b_InitBeaconParameters(padapter);
+ _InitInterrupt(padapter);
+ _InitBurstPktLen_8723BS(padapter);
+
+ /* YJ, TODO */
+ rtw_write8(padapter, REG_SECONDARY_CCA_CTRL_8723B, 0x3); /* CCA */
+ rtw_write8(padapter, 0x976, 0); /* hpfan_todo: 2nd CCA related */
+
+ rtw_write16(padapter, REG_PKT_VO_VI_LIFE_TIME, 0x0400); /* unit: 256us. 256ms */
+ rtw_write16(padapter, REG_PKT_BE_BK_LIFE_TIME, 0x0400); /* unit: 256us. 256ms */
+
+ invalidate_cam_all(padapter);
+
+ rtw_hal_set_chnl_bw(padapter, padapter->registrypriv.channel,
+ CHANNEL_WIDTH_20, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HAL_PRIME_CHNL_OFFSET_DONT_CARE);
+
+ /* Record original value for template. This is arough data, we can only use the data */
+ /* for power adjust. The value can not be adjustde according to different power!!! */
+/* pHalData->OriginalCckTxPwrIdx = pHalData->CurrentCckTxPwrIdx; */
+/* pHalData->OriginalOfdm24GTxPwrIdx = pHalData->CurrentOfdm24GTxPwrIdx; */
+
+ rtl8723b_InitAntenna_Selection(padapter);
+
+ /* */
+ /* Disable BAR, suggested by Scott */
+ /* 2010.04.09 add by hpfan */
+ /* */
+ rtw_write32(padapter, REG_BAR_MODE_CTRL, 0x0201ffff);
+
+ /* HW SEQ CTRL */
+ /* set 0x0 to 0xFF by tynli. Default enable HW SEQ NUM. */
+ rtw_write8(padapter, REG_HWSEQ_CTRL, 0xFF);
+
+
+ /* */
+ /* Configure SDIO TxRx Control to enable Rx DMA timer masking. */
+ /* 2010.02.24. */
+ /* */
+ rtw_write32(padapter, SDIO_LOCAL_BASE | SDIO_REG_TX_CTRL, 0);
+
+ _RfPowerSave(padapter);
+
+
+ rtl8723b_InitHalDm(padapter);
+
+ /* */
+ /* Update current Tx FIFO page status. */
+ /* */
+ HalQueryTxBufferStatus8723BSdio(padapter);
+ HalQueryTxOQTBufferStatus8723BSdio(padapter);
+ pHalData->SdioTxOQTMaxFreeSpace = pHalData->SdioTxOQTFreeSpace;
+
+ /* Enable MACTXEN/MACRXEN block */
+ u1bTmp = rtw_read8(padapter, REG_CR);
+ u1bTmp |= (MACTXEN | MACRXEN);
+ rtw_write8(padapter, REG_CR, u1bTmp);
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_NAV_UPPER, (u8 *)&NavUpper);
+
+ /* ack for xmit mgmt frames. */
+ rtw_write32(padapter, REG_FWHW_TXQ_CTRL, rtw_read32(padapter, REG_FWHW_TXQ_CTRL) | BIT(12));
+
+/* pHalData->PreRpwmVal = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_HRPWM1) & 0x80; */
+
+ {
+ pwrctrlpriv->rf_pwrstate = rf_on;
+
+ if (pwrctrlpriv->rf_pwrstate == rf_on) {
+ struct pwrctrl_priv *pwrpriv;
+ unsigned long start_time;
+ u8 restore_iqk_rst;
+ u8 b2Ant;
+ u8 h2cCmdBuf;
+
+ pwrpriv = adapter_to_pwrctl(padapter);
+
+ PHY_LCCalibrate_8723B(&pHalData->odmpriv);
+
+ /* Inform WiFi FW that it is the beginning of IQK */
+ h2cCmdBuf = 1;
+ FillH2CCmd8723B(padapter, H2C_8723B_BT_WLAN_CALIBRATION, 1, &h2cCmdBuf);
+
+ start_time = jiffies;
+ do {
+ if (rtw_read8(padapter, 0x1e7) & 0x01)
+ break;
+
+ msleep(50);
+ } while (jiffies_to_msecs(jiffies - start_time) <= 400);
+
+ hal_btcoex_IQKNotify(padapter, true);
+
+ restore_iqk_rst = pwrpriv->bips_processing;
+ b2Ant = pHalData->EEPROMBluetoothAntNum == Ant_x2;
+ PHY_IQCalibrate_8723B(padapter, false, restore_iqk_rst, b2Ant, pHalData->ant_path);
+ pHalData->odmpriv.RFCalibrateInfo.bIQKInitialized = true;
+
+ hal_btcoex_IQKNotify(padapter, false);
+
+ /* Inform WiFi FW that it is the finish of IQK */
+ h2cCmdBuf = 0;
+ FillH2CCmd8723B(padapter, H2C_8723B_BT_WLAN_CALIBRATION, 1, &h2cCmdBuf);
+
+ ODM_TXPowerTrackingCheck(&pHalData->odmpriv);
+ }
+ }
+
+ /* Init BT hw config. */
+ hal_btcoex_InitHwConfig(padapter, false);
+
+ return _SUCCESS;
+}
+
+/* */
+/* Description: */
+/* RTL8723e card disable power sequence v003 which suggested by Scott. */
+/* */
+/* First created by tynli. 2011.01.28. */
+/* */
+static void CardDisableRTL8723BSdio(struct adapter *padapter)
+{
+ u8 u1bTmp;
+ u8 bMacPwrCtrlOn;
+
+ /* Run LPS WL RFOFF flow */
+ HalPwrSeqCmdParsing(padapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, rtl8723B_enter_lps_flow);
+
+ /* ==== Reset digital sequence ====== */
+
+ u1bTmp = rtw_read8(padapter, REG_MCUFWDL);
+ if ((u1bTmp & RAM_DL_SEL) && padapter->bFWReady) /* 8051 RAM code */
+ rtl8723b_FirmwareSelfReset(padapter);
+
+ /* Reset MCU 0x2[10]= 0. Suggested by Filen. 2011.01.26. by tynli. */
+ u1bTmp = rtw_read8(padapter, REG_SYS_FUNC_EN + 1);
+ u1bTmp &= ~BIT(2); /* 0x2[10], FEN_CPUEN */
+ rtw_write8(padapter, REG_SYS_FUNC_EN + 1, u1bTmp);
+
+ /* MCUFWDL 0x80[1:0]= 0 */
+ /* reset MCU ready status */
+ rtw_write8(padapter, REG_MCUFWDL, 0);
+
+ /* Reset MCU IO Wrapper, added by Roger, 2011.08.30 */
+ u1bTmp = rtw_read8(padapter, REG_RSV_CTRL + 1);
+ u1bTmp &= ~BIT(0);
+ rtw_write8(padapter, REG_RSV_CTRL + 1, u1bTmp);
+ u1bTmp = rtw_read8(padapter, REG_RSV_CTRL + 1);
+ u1bTmp |= BIT(0);
+ rtw_write8(padapter, REG_RSV_CTRL+1, u1bTmp);
+
+ /* ==== Reset digital sequence end ====== */
+
+ bMacPwrCtrlOn = false; /* Disable CMD53 R/W */
+ rtw_hal_set_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
+ HalPwrSeqCmdParsing(padapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, rtl8723B_card_disable_flow);
+}
+
+static u32 rtl8723bs_hal_deinit(struct adapter *padapter)
+{
+ struct dvobj_priv *psdpriv = padapter->dvobj;
+ struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
+
+ if (padapter->hw_init_completed) {
+ if (adapter_to_pwrctl(padapter)->bips_processing) {
+ if (padapter->netif_up) {
+ int cnt = 0;
+ u8 val8 = 0;
+
+ rtl8723b_set_FwPwrModeInIPS_cmd(padapter, 0x3);
+ /* poll 0x1cc to make sure H2C command already finished by FW; MAC_0x1cc = 0 means H2C done by FW. */
+ do {
+ val8 = rtw_read8(padapter, REG_HMETFR);
+ cnt++;
+ mdelay(10);
+ } while (cnt < 100 && (val8 != 0));
+ /* H2C done, enter 32k */
+ if (val8 == 0) {
+ /* ser rpwm to enter 32k */
+ val8 = rtw_read8(padapter, SDIO_LOCAL_BASE | SDIO_REG_HRPWM1);
+ val8 += 0x80;
+ val8 |= BIT(0);
+ rtw_write8(padapter, SDIO_LOCAL_BASE | SDIO_REG_HRPWM1, val8);
+ adapter_to_pwrctl(padapter)->tog = (val8 + 0x80) & 0x80;
+ cnt = val8 = 0;
+ do {
+ val8 = rtw_read8(padapter, REG_CR);
+ cnt++;
+ mdelay(10);
+ } while (cnt < 100 && (val8 != 0xEA));
+ }
+
+ adapter_to_pwrctl(padapter)->pre_ips_type = 0;
+
+ } else {
+ pdbgpriv->dbg_carddisable_cnt++;
+ CardDisableRTL8723BSdio(padapter);
+
+ adapter_to_pwrctl(padapter)->pre_ips_type = 1;
+ }
+
+ } else {
+ pdbgpriv->dbg_carddisable_cnt++;
+ CardDisableRTL8723BSdio(padapter);
+ }
+ } else
+ pdbgpriv->dbg_deinit_fail_cnt++;
+
+ return _SUCCESS;
+}
+
+static u32 rtl8723bs_inirp_init(struct adapter *padapter)
+{
+ return _SUCCESS;
+}
+
+static u32 rtl8723bs_inirp_deinit(struct adapter *padapter)
+{
+ return _SUCCESS;
+}
+
+static void rtl8723bs_init_default_value(struct adapter *padapter)
+{
+ struct hal_com_data *pHalData;
+
+
+ pHalData = GET_HAL_DATA(padapter);
+
+ rtl8723b_init_default_value(padapter);
+
+ /* interface related variable */
+ pHalData->SdioRxFIFOCnt = 0;
+}
+
+static void rtl8723bs_interface_configure(struct adapter *padapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+ struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
+ bool bWiFiConfig = pregistrypriv->wifi_spec;
+
+
+ pdvobjpriv->RtOutPipe[0] = WLAN_TX_HIQ_DEVICE_ID;
+ pdvobjpriv->RtOutPipe[1] = WLAN_TX_MIQ_DEVICE_ID;
+ pdvobjpriv->RtOutPipe[2] = WLAN_TX_LOQ_DEVICE_ID;
+
+ if (bWiFiConfig)
+ pHalData->OutEpNumber = 2;
+ else
+ pHalData->OutEpNumber = SDIO_MAX_TX_QUEUE;
+
+ switch (pHalData->OutEpNumber) {
+ case 3:
+ pHalData->OutEpQueueSel = TX_SELE_HQ | TX_SELE_LQ | TX_SELE_NQ;
+ break;
+ case 2:
+ pHalData->OutEpQueueSel = TX_SELE_HQ | TX_SELE_NQ;
+ break;
+ case 1:
+ pHalData->OutEpQueueSel = TX_SELE_HQ;
+ break;
+ default:
+ break;
+ }
+
+ Hal_MappingOutPipe(padapter, pHalData->OutEpNumber);
+}
+
+/* */
+/* Description: */
+/* We should set Efuse cell selection to WiFi cell in default. */
+/* */
+/* Assumption: */
+/* PASSIVE_LEVEL */
+/* */
+/* Added by Roger, 2010.11.23. */
+/* */
+static void _EfuseCellSel(struct adapter *padapter)
+{
+ u32 value32;
+
+ value32 = rtw_read32(padapter, EFUSE_TEST);
+ value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_WIFI_SEL_0);
+ rtw_write32(padapter, EFUSE_TEST, value32);
+}
+
+static void _ReadRFType(struct adapter *Adapter)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+
+ pHalData->rf_chip = RF_6052;
+}
+
+
+static void Hal_EfuseParseMACAddr_8723BS(
+ struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
+)
+{
+ u16 i;
+ u8 sMacAddr[6] = {0x00, 0xE0, 0x4C, 0xb7, 0x23, 0x00};
+ struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
+
+ if (AutoLoadFail) {
+/* sMacAddr[5] = (u8)GetRandomNumber(1, 254); */
+ for (i = 0; i < 6; i++)
+ pEEPROM->mac_addr[i] = sMacAddr[i];
+ } else {
+ /* Read Permanent MAC address */
+ memcpy(pEEPROM->mac_addr, &hwinfo[EEPROM_MAC_ADDR_8723BS], ETH_ALEN);
+ }
+}
+
+static void Hal_EfuseParseBoardType_8723BS(
+ struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
+)
+{
+ struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+
+ if (!AutoLoadFail) {
+ pHalData->BoardType = (hwinfo[EEPROM_RF_BOARD_OPTION_8723B] & 0xE0) >> 5;
+ if (pHalData->BoardType == 0xFF)
+ pHalData->BoardType = (EEPROM_DEFAULT_BOARD_OPTION & 0xE0) >> 5;
+ } else
+ pHalData->BoardType = 0;
+}
+
+static void _ReadEfuseInfo8723BS(struct adapter *padapter)
+{
+ struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
+ u8 *hwinfo = NULL;
+
+ /* */
+ /* This part read and parse the eeprom/efuse content */
+ /* */
+
+ hwinfo = pEEPROM->efuse_eeprom_data;
+
+ Hal_InitPGData(padapter, hwinfo);
+
+ Hal_EfuseParseIDCode(padapter, hwinfo);
+ Hal_EfuseParseEEPROMVer_8723B(padapter, hwinfo, pEEPROM->bautoload_fail_flag);
+
+ Hal_EfuseParseMACAddr_8723BS(padapter, hwinfo, pEEPROM->bautoload_fail_flag);
+
+ Hal_EfuseParseTxPowerInfo_8723B(padapter, hwinfo, pEEPROM->bautoload_fail_flag);
+ Hal_EfuseParseBoardType_8723BS(padapter, hwinfo, pEEPROM->bautoload_fail_flag);
+
+ /* */
+ /* Read Bluetooth co-exist and initialize */
+ /* */
+ Hal_EfuseParsePackageType_8723B(padapter, hwinfo, pEEPROM->bautoload_fail_flag);
+ Hal_EfuseParseBTCoexistInfo_8723B(padapter, hwinfo, pEEPROM->bautoload_fail_flag);
+ Hal_EfuseParseChnlPlan_8723B(padapter, hwinfo, pEEPROM->bautoload_fail_flag);
+ Hal_EfuseParseXtal_8723B(padapter, hwinfo, pEEPROM->bautoload_fail_flag);
+ Hal_EfuseParseThermalMeter_8723B(padapter, hwinfo, pEEPROM->bautoload_fail_flag);
+ Hal_EfuseParseAntennaDiversity_8723B(padapter, hwinfo, pEEPROM->bautoload_fail_flag);
+ Hal_EfuseParseCustomerID_8723B(padapter, hwinfo, pEEPROM->bautoload_fail_flag);
+
+ Hal_EfuseParseVoltage_8723B(padapter, hwinfo, pEEPROM->bautoload_fail_flag);
+
+ Hal_ReadRFGainOffset(padapter, hwinfo, pEEPROM->bautoload_fail_flag);
+}
+
+static void _ReadPROMContent(struct adapter *padapter)
+{
+ struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
+ u8 eeValue;
+
+ eeValue = rtw_read8(padapter, REG_9346CR);
+ /* To check system boot selection. */
+ pEEPROM->EepromOrEfuse = (eeValue & BOOT_FROM_EEPROM) ? true : false;
+ pEEPROM->bautoload_fail_flag = (eeValue & EEPROM_EN) ? false : true;
+
+/* pHalData->EEType = IS_BOOT_FROM_EEPROM(Adapter) ? EEPROM_93C46 : EEPROM_BOOT_EFUSE; */
+
+ _ReadEfuseInfo8723BS(padapter);
+}
+
+static void _InitOtherVariable(struct adapter *Adapter)
+{
+}
+
+/* */
+/* Description: */
+/* Read HW adapter information by E-Fuse or EEPROM according CR9346 reported. */
+/* */
+/* Assumption: */
+/* PASSIVE_LEVEL (SDIO interface) */
+/* */
+/* */
+static s32 _ReadAdapterInfo8723BS(struct adapter *padapter)
+{
+ u8 val8;
+
+ /* before access eFuse, make sure card enable has been called */
+ if (!padapter->hw_init_completed)
+ _InitPowerOn_8723BS(padapter);
+
+
+ val8 = rtw_read8(padapter, 0x4e);
+ val8 |= BIT(6);
+ rtw_write8(padapter, 0x4e, val8);
+
+ _EfuseCellSel(padapter);
+ _ReadRFType(padapter);
+ _ReadPROMContent(padapter);
+ _InitOtherVariable(padapter);
+
+ if (!padapter->hw_init_completed) {
+ rtw_write8(padapter, 0x67, 0x00); /* for BT, Switch Ant control to BT */
+ CardDisableRTL8723BSdio(padapter);/* for the power consumption issue, wifi ko module is loaded during booting, but wifi GUI is off */
+ }
+
+ return _SUCCESS;
+}
+
+static void ReadAdapterInfo8723BS(struct adapter *padapter)
+{
+ /* Read EEPROM size before call any EEPROM function */
+ padapter->EepromAddressSize = GetEEPROMSize8723B(padapter);
+
+ _ReadAdapterInfo8723BS(padapter);
+}
+
+/*
+ * If variable not handled here,
+ * some variables will be processed in SetHwReg8723B()
+ */
+static void SetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val)
+{
+ u8 val8;
+
+ switch (variable) {
+ case HW_VAR_SET_RPWM:
+ /* rpwm value only use BIT0(clock bit) , BIT6(Ack bit), and BIT7(Toggle bit) */
+ /* BIT0 value - 1: 32k, 0:40MHz. */
+ /* BIT6 value - 1: report cpwm value after success set, 0:do not report. */
+ /* BIT7 value - Toggle bit change. */
+ {
+ val8 = *val;
+ val8 &= 0xC1;
+ rtw_write8(padapter, SDIO_LOCAL_BASE | SDIO_REG_HRPWM1, val8);
+ }
+ break;
+ case HW_VAR_SET_REQ_FW_PS:
+ {
+ u8 req_fw_ps = 0;
+ req_fw_ps = rtw_read8(padapter, 0x8f);
+ req_fw_ps |= 0x10;
+ rtw_write8(padapter, 0x8f, req_fw_ps);
+ }
+ break;
+ case HW_VAR_RXDMA_AGG_PG_TH:
+ val8 = *val;
+ break;
+
+ case HW_VAR_DM_IN_LPS:
+ rtl8723b_hal_dm_in_lps(padapter);
+ break;
+ default:
+ SetHwReg8723B(padapter, variable, val);
+ break;
+ }
+}
+
+/*
+ * If variable not handled here,
+ * some variables will be processed in GetHwReg8723B()
+ */
+static void GetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val)
+{
+ switch (variable) {
+ case HW_VAR_CPWM:
+ *val = rtw_read8(padapter, SDIO_LOCAL_BASE | SDIO_REG_HCPWM1_8723B);
+ break;
+
+ case HW_VAR_FW_PS_STATE:
+ {
+ /* 3. read dword 0x88 driver read fw ps state */
+ *((u16 *)val) = rtw_read16(padapter, 0x88);
+ }
+ break;
+ default:
+ GetHwReg8723B(padapter, variable, val);
+ break;
+ }
+}
+
+static void SetHwRegWithBuf8723B(struct adapter *padapter, u8 variable, u8 *pbuf, int len)
+{
+ switch (variable) {
+ case HW_VAR_C2H_HANDLE:
+ C2HPacketHandler_8723B(padapter, pbuf, len);
+ break;
+ default:
+ break;
+ }
+}
+
+/* */
+/* Description: */
+/* Query setting of specified variable. */
+/* */
+static u8 GetHalDefVar8723BSDIO(
+ struct adapter *Adapter, enum hal_def_variable eVariable, void *pValue
+)
+{
+ u8 bResult = _SUCCESS;
+
+ switch (eVariable) {
+ case HAL_DEF_IS_SUPPORT_ANT_DIV:
+ break;
+ case HAL_DEF_CURRENT_ANTENNA:
+ break;
+ case HW_VAR_MAX_RX_AMPDU_FACTOR:
+ /* Stanley@BB.SD3 suggests 16K can get stable performance */
+ /* coding by Lucas@20130730 */
+ *(u32 *)pValue = IEEE80211_HT_MAX_AMPDU_16K;
+ break;
+ default:
+ bResult = GetHalDefVar8723B(Adapter, eVariable, pValue);
+ break;
+ }
+
+ return bResult;
+}
+
+/* */
+/* Description: */
+/* Change default setting of specified variable. */
+/* */
+static u8 SetHalDefVar8723BSDIO(struct adapter *Adapter,
+ enum hal_def_variable eVariable, void *pValue)
+{
+ return SetHalDefVar8723B(Adapter, eVariable, pValue);
+}
+
+void rtl8723bs_set_hal_ops(struct adapter *padapter)
+{
+ struct hal_ops *pHalFunc = &padapter->HalFunc;
+
+ rtl8723b_set_hal_ops(pHalFunc);
+
+ pHalFunc->hal_init = &rtl8723bs_hal_init;
+ pHalFunc->hal_deinit = &rtl8723bs_hal_deinit;
+
+ pHalFunc->inirp_init = &rtl8723bs_inirp_init;
+ pHalFunc->inirp_deinit = &rtl8723bs_inirp_deinit;
+
+ pHalFunc->init_xmit_priv = &rtl8723bs_init_xmit_priv;
+ pHalFunc->free_xmit_priv = &rtl8723bs_free_xmit_priv;
+
+ pHalFunc->init_recv_priv = &rtl8723bs_init_recv_priv;
+ pHalFunc->free_recv_priv = &rtl8723bs_free_recv_priv;
+
+ pHalFunc->init_default_value = &rtl8723bs_init_default_value;
+ pHalFunc->intf_chip_configure = &rtl8723bs_interface_configure;
+ pHalFunc->read_adapter_info = &ReadAdapterInfo8723BS;
+
+ pHalFunc->enable_interrupt = &EnableInterrupt8723BSdio;
+ pHalFunc->disable_interrupt = &DisableInterrupt8723BSdio;
+ pHalFunc->check_ips_status = &CheckIPSStatus;
+ pHalFunc->SetHwRegHandler = &SetHwReg8723BS;
+ pHalFunc->GetHwRegHandler = &GetHwReg8723BS;
+ pHalFunc->SetHwRegHandlerWithBuf = &SetHwRegWithBuf8723B;
+ pHalFunc->GetHalDefVarHandler = &GetHalDefVar8723BSDIO;
+ pHalFunc->SetHalDefVarHandler = &SetHalDefVar8723BSDIO;
+
+ pHalFunc->hal_xmit = &rtl8723bs_hal_xmit;
+ pHalFunc->mgnt_xmit = &rtl8723bs_mgnt_xmit;
+ pHalFunc->hal_xmitframe_enqueue = &rtl8723bs_hal_xmitframe_enqueue;
+}
diff --git a/drivers/staging/rtl8723bs/hal/sdio_ops.c b/drivers/staging/rtl8723bs/hal/sdio_ops.c
new file mode 100644
index 000000000..107f427ee
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/sdio_ops.c
@@ -0,0 +1,1012 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ *******************************************************************************/
+#include <drv_types.h>
+#include <rtw_debug.h>
+#include <rtl8723b_hal.h>
+
+/* */
+/* Description: */
+/* The following mapping is for SDIO host local register space. */
+/* */
+/* Creadted by Roger, 2011.01.31. */
+/* */
+static void hal_sdio_get_cmd_addr_8723b(
+ struct adapter *adapter,
+ u8 device_id,
+ u32 addr,
+ u32 *cmdaddr
+)
+{
+ switch (device_id) {
+ case SDIO_LOCAL_DEVICE_ID:
+ *cmdaddr = ((SDIO_LOCAL_DEVICE_ID << 13) | (addr & SDIO_LOCAL_MSK));
+ break;
+
+ case WLAN_IOREG_DEVICE_ID:
+ *cmdaddr = ((WLAN_IOREG_DEVICE_ID << 13) | (addr & WLAN_IOREG_MSK));
+ break;
+
+ case WLAN_TX_HIQ_DEVICE_ID:
+ *cmdaddr = ((WLAN_TX_HIQ_DEVICE_ID << 13) | (addr & WLAN_FIFO_MSK));
+ break;
+
+ case WLAN_TX_MIQ_DEVICE_ID:
+ *cmdaddr = ((WLAN_TX_MIQ_DEVICE_ID << 13) | (addr & WLAN_FIFO_MSK));
+ break;
+
+ case WLAN_TX_LOQ_DEVICE_ID:
+ *cmdaddr = ((WLAN_TX_LOQ_DEVICE_ID << 13) | (addr & WLAN_FIFO_MSK));
+ break;
+
+ case WLAN_RX0FF_DEVICE_ID:
+ *cmdaddr = ((WLAN_RX0FF_DEVICE_ID << 13) | (addr & WLAN_RX0FF_MSK));
+ break;
+
+ default:
+ break;
+ }
+}
+
+static u8 get_deviceid(u32 addr)
+{
+ u8 devide_id;
+ u16 pseudo_id;
+
+ pseudo_id = (u16)(addr >> 16);
+ switch (pseudo_id) {
+ case 0x1025:
+ devide_id = SDIO_LOCAL_DEVICE_ID;
+ break;
+
+ case 0x1026:
+ devide_id = WLAN_IOREG_DEVICE_ID;
+ break;
+
+ case 0x1031:
+ devide_id = WLAN_TX_HIQ_DEVICE_ID;
+ break;
+
+ case 0x1032:
+ devide_id = WLAN_TX_MIQ_DEVICE_ID;
+ break;
+
+ case 0x1033:
+ devide_id = WLAN_TX_LOQ_DEVICE_ID;
+ break;
+
+ case 0x1034:
+ devide_id = WLAN_RX0FF_DEVICE_ID;
+ break;
+
+ default:
+ devide_id = WLAN_IOREG_DEVICE_ID;
+ break;
+ }
+
+ return devide_id;
+}
+
+static u32 _cvrt2ftaddr(const u32 addr, u8 *pdevice_id, u16 *poffset)
+{
+ u8 device_id;
+ u16 offset;
+ u32 ftaddr;
+
+ device_id = get_deviceid(addr);
+ offset = 0;
+
+ switch (device_id) {
+ case SDIO_LOCAL_DEVICE_ID:
+ offset = addr & SDIO_LOCAL_MSK;
+ break;
+
+ case WLAN_TX_HIQ_DEVICE_ID:
+ case WLAN_TX_MIQ_DEVICE_ID:
+ case WLAN_TX_LOQ_DEVICE_ID:
+ offset = addr & WLAN_FIFO_MSK;
+ break;
+
+ case WLAN_RX0FF_DEVICE_ID:
+ offset = addr & WLAN_RX0FF_MSK;
+ break;
+
+ case WLAN_IOREG_DEVICE_ID:
+ default:
+ device_id = WLAN_IOREG_DEVICE_ID;
+ offset = addr & WLAN_IOREG_MSK;
+ break;
+ }
+ ftaddr = (device_id << 13) | offset;
+
+ if (pdevice_id)
+ *pdevice_id = device_id;
+ if (poffset)
+ *poffset = offset;
+
+ return ftaddr;
+}
+
+static u8 sdio_read8(struct intf_hdl *intfhdl, u32 addr)
+{
+ u32 ftaddr;
+ ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
+
+ return sd_read8(intfhdl, ftaddr, NULL);
+}
+
+static u16 sdio_read16(struct intf_hdl *intfhdl, u32 addr)
+{
+ u32 ftaddr;
+ __le16 le_tmp;
+
+ ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
+ sd_cmd52_read(intfhdl, ftaddr, 2, (u8 *)&le_tmp);
+
+ return le16_to_cpu(le_tmp);
+}
+
+static u32 sdio_read32(struct intf_hdl *intfhdl, u32 addr)
+{
+ struct adapter *adapter;
+ u8 mac_pwr_ctrl_on;
+ u8 device_id;
+ u16 offset;
+ u32 ftaddr;
+ u8 shift;
+ u32 val;
+ s32 __maybe_unused err;
+ __le32 le_tmp;
+
+ adapter = intfhdl->padapter;
+ ftaddr = _cvrt2ftaddr(addr, &device_id, &offset);
+
+ rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
+ if (
+ ((device_id == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
+ (!mac_pwr_ctrl_on) ||
+ (adapter_to_pwrctl(adapter)->fw_current_in_ps_mode)
+ ) {
+ err = sd_cmd52_read(intfhdl, ftaddr, 4, (u8 *)&le_tmp);
+ return le32_to_cpu(le_tmp);
+ }
+
+ /* 4 bytes alignment */
+ shift = ftaddr & 0x3;
+ if (shift == 0) {
+ val = sd_read32(intfhdl, ftaddr, NULL);
+ } else {
+ u8 *tmpbuf;
+
+ tmpbuf = rtw_malloc(8);
+ if (!tmpbuf)
+ return SDIO_ERR_VAL32;
+
+ ftaddr &= ~(u16)0x3;
+ sd_read(intfhdl, ftaddr, 8, tmpbuf);
+ memcpy(&le_tmp, tmpbuf + shift, 4);
+ val = le32_to_cpu(le_tmp);
+
+ kfree(tmpbuf);
+ }
+ return val;
+}
+
+static s32 sdio_readN(struct intf_hdl *intfhdl, u32 addr, u32 cnt, u8 *buf)
+{
+ struct adapter *adapter;
+ u8 mac_pwr_ctrl_on;
+ u8 device_id;
+ u16 offset;
+ u32 ftaddr;
+ u8 shift;
+ s32 err;
+
+ adapter = intfhdl->padapter;
+ err = 0;
+
+ ftaddr = _cvrt2ftaddr(addr, &device_id, &offset);
+
+ rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
+ if (
+ ((device_id == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
+ (!mac_pwr_ctrl_on) ||
+ (adapter_to_pwrctl(adapter)->fw_current_in_ps_mode)
+ )
+ return sd_cmd52_read(intfhdl, ftaddr, cnt, buf);
+
+ /* 4 bytes alignment */
+ shift = ftaddr & 0x3;
+ if (shift == 0) {
+ err = sd_read(intfhdl, ftaddr, cnt, buf);
+ } else {
+ u8 *tmpbuf;
+ u32 n;
+
+ ftaddr &= ~(u16)0x3;
+ n = cnt + shift;
+ tmpbuf = rtw_malloc(n);
+ if (!tmpbuf)
+ return -1;
+
+ err = sd_read(intfhdl, ftaddr, n, tmpbuf);
+ if (!err)
+ memcpy(buf, tmpbuf + shift, cnt);
+ kfree(tmpbuf);
+ }
+ return err;
+}
+
+static s32 sdio_write8(struct intf_hdl *intfhdl, u32 addr, u8 val)
+{
+ u32 ftaddr;
+ s32 err;
+
+ ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
+ sd_write8(intfhdl, ftaddr, val, &err);
+
+ return err;
+}
+
+static s32 sdio_write16(struct intf_hdl *intfhdl, u32 addr, u16 val)
+{
+ u32 ftaddr;
+ __le16 le_tmp;
+
+ ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
+ le_tmp = cpu_to_le16(val);
+ return sd_cmd52_write(intfhdl, ftaddr, 2, (u8 *)&le_tmp);
+}
+
+static s32 sdio_write32(struct intf_hdl *intfhdl, u32 addr, u32 val)
+{
+ struct adapter *adapter;
+ u8 mac_pwr_ctrl_on;
+ u8 device_id;
+ u16 offset;
+ u32 ftaddr;
+ u8 shift;
+ s32 err;
+ __le32 le_tmp;
+
+ adapter = intfhdl->padapter;
+ err = 0;
+
+ ftaddr = _cvrt2ftaddr(addr, &device_id, &offset);
+
+ rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
+ if (
+ ((device_id == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
+ (!mac_pwr_ctrl_on) ||
+ (adapter_to_pwrctl(adapter)->fw_current_in_ps_mode)
+ ) {
+ le_tmp = cpu_to_le32(val);
+
+ return sd_cmd52_write(intfhdl, ftaddr, 4, (u8 *)&le_tmp);
+ }
+
+ /* 4 bytes alignment */
+ shift = ftaddr & 0x3;
+ if (shift == 0) {
+ sd_write32(intfhdl, ftaddr, val, &err);
+ } else {
+ le_tmp = cpu_to_le32(val);
+ err = sd_cmd52_write(intfhdl, ftaddr, 4, (u8 *)&le_tmp);
+ }
+ return err;
+}
+
+static s32 sdio_writeN(struct intf_hdl *intfhdl, u32 addr, u32 cnt, u8 *buf)
+{
+ struct adapter *adapter;
+ u8 mac_pwr_ctrl_on;
+ u8 device_id;
+ u16 offset;
+ u32 ftaddr;
+ u8 shift;
+ s32 err;
+
+ adapter = intfhdl->padapter;
+ err = 0;
+
+ ftaddr = _cvrt2ftaddr(addr, &device_id, &offset);
+
+ rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
+ if (
+ ((device_id == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
+ (!mac_pwr_ctrl_on) ||
+ (adapter_to_pwrctl(adapter)->fw_current_in_ps_mode)
+ )
+ return sd_cmd52_write(intfhdl, ftaddr, cnt, buf);
+
+ shift = ftaddr & 0x3;
+ if (shift == 0) {
+ err = sd_write(intfhdl, ftaddr, cnt, buf);
+ } else {
+ u8 *tmpbuf;
+ u32 n;
+
+ ftaddr &= ~(u16)0x3;
+ n = cnt + shift;
+ tmpbuf = rtw_malloc(n);
+ if (!tmpbuf)
+ return -1;
+ err = sd_read(intfhdl, ftaddr, 4, tmpbuf);
+ if (err) {
+ kfree(tmpbuf);
+ return err;
+ }
+ memcpy(tmpbuf + shift, buf, cnt);
+ err = sd_write(intfhdl, ftaddr, n, tmpbuf);
+ kfree(tmpbuf);
+ }
+ return err;
+}
+
+static void sdio_read_mem(
+ struct intf_hdl *intfhdl,
+ u32 addr,
+ u32 cnt,
+ u8 *rmem
+)
+{
+ sdio_readN(intfhdl, addr, cnt, rmem);
+}
+
+static void sdio_write_mem(
+ struct intf_hdl *intfhdl,
+ u32 addr,
+ u32 cnt,
+ u8 *wmem
+)
+{
+ sdio_writeN(intfhdl, addr, cnt, wmem);
+}
+
+/*
+ * Description:
+ *Read from RX FIFO
+ *Round read size to block size,
+ *and make sure data transfer will be done in one command.
+ *
+ * Parameters:
+ *intfhdl a pointer of intf_hdl
+ *addr port ID
+ *cnt size to read
+ *rmem address to put data
+ *
+ * Return:
+ *_SUCCESS(1) Success
+ *_FAIL(0) Fail
+ */
+static u32 sdio_read_port(
+ struct intf_hdl *intfhdl,
+ u32 addr,
+ u32 cnt,
+ u8 *mem
+)
+{
+ struct adapter *adapter;
+ struct sdio_data *psdio;
+ struct hal_com_data *hal;
+ s32 err;
+
+ adapter = intfhdl->padapter;
+ psdio = &adapter_to_dvobj(adapter)->intf_data;
+ hal = GET_HAL_DATA(adapter);
+
+ hal_sdio_get_cmd_addr_8723b(adapter, addr, hal->SdioRxFIFOCnt++, &addr);
+
+ if (cnt > psdio->block_transfer_len)
+ cnt = _RND(cnt, psdio->block_transfer_len);
+
+ err = _sd_read(intfhdl, addr, cnt, mem);
+
+ if (err)
+ return _FAIL;
+ return _SUCCESS;
+}
+
+/*
+ * Description:
+ *Write to TX FIFO
+ *Align write size block size,
+ *and make sure data could be written in one command.
+ *
+ * Parameters:
+ *intfhdl a pointer of intf_hdl
+ *addr port ID
+ *cnt size to write
+ *wmem data pointer to write
+ *
+ * Return:
+ *_SUCCESS(1) Success
+ *_FAIL(0) Fail
+ */
+static u32 sdio_write_port(
+ struct intf_hdl *intfhdl,
+ u32 addr,
+ u32 cnt,
+ u8 *mem
+)
+{
+ struct adapter *adapter;
+ struct sdio_data *psdio;
+ s32 err;
+ struct xmit_buf *xmitbuf = (struct xmit_buf *)mem;
+
+ adapter = intfhdl->padapter;
+ psdio = &adapter_to_dvobj(adapter)->intf_data;
+
+ if (!adapter->hw_init_completed)
+ return _FAIL;
+
+ cnt = round_up(cnt, 4);
+ hal_sdio_get_cmd_addr_8723b(adapter, addr, cnt >> 2, &addr);
+
+ if (cnt > psdio->block_transfer_len)
+ cnt = _RND(cnt, psdio->block_transfer_len);
+
+ err = sd_write(intfhdl, addr, cnt, xmitbuf->pdata);
+
+ rtw_sctx_done_err(
+ &xmitbuf->sctx,
+ err ? RTW_SCTX_DONE_WRITE_PORT_ERR : RTW_SCTX_DONE_SUCCESS
+ );
+
+ if (err)
+ return _FAIL;
+ return _SUCCESS;
+}
+
+void sdio_set_intf_ops(struct adapter *adapter, struct _io_ops *ops)
+{
+ ops->_read8 = &sdio_read8;
+ ops->_read16 = &sdio_read16;
+ ops->_read32 = &sdio_read32;
+ ops->_read_mem = &sdio_read_mem;
+ ops->_read_port = &sdio_read_port;
+
+ ops->_write8 = &sdio_write8;
+ ops->_write16 = &sdio_write16;
+ ops->_write32 = &sdio_write32;
+ ops->_writeN = &sdio_writeN;
+ ops->_write_mem = &sdio_write_mem;
+ ops->_write_port = &sdio_write_port;
+}
+
+/*
+ * Todo: align address to 4 bytes.
+ */
+static s32 _sdio_local_read(
+ struct adapter *adapter,
+ u32 addr,
+ u32 cnt,
+ u8 *buf
+)
+{
+ struct intf_hdl *intfhdl;
+ u8 mac_pwr_ctrl_on;
+ s32 err;
+ u8 *tmpbuf;
+ u32 n;
+
+ intfhdl = &adapter->iopriv.intf;
+
+ hal_sdio_get_cmd_addr_8723b(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
+
+ rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
+ if (!mac_pwr_ctrl_on)
+ return _sd_cmd52_read(intfhdl, addr, cnt, buf);
+
+ n = round_up(cnt, 4);
+ tmpbuf = rtw_malloc(n);
+ if (!tmpbuf)
+ return -1;
+
+ err = _sd_read(intfhdl, addr, n, tmpbuf);
+ if (!err)
+ memcpy(buf, tmpbuf, cnt);
+
+ kfree(tmpbuf);
+
+ return err;
+}
+
+/*
+ * Todo: align address to 4 bytes.
+ */
+s32 sdio_local_read(
+ struct adapter *adapter,
+ u32 addr,
+ u32 cnt,
+ u8 *buf
+)
+{
+ struct intf_hdl *intfhdl;
+ u8 mac_pwr_ctrl_on;
+ s32 err;
+ u8 *tmpbuf;
+ u32 n;
+
+ intfhdl = &adapter->iopriv.intf;
+
+ hal_sdio_get_cmd_addr_8723b(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
+
+ rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
+ if (
+ (!mac_pwr_ctrl_on) ||
+ (adapter_to_pwrctl(adapter)->fw_current_in_ps_mode)
+ )
+ return sd_cmd52_read(intfhdl, addr, cnt, buf);
+
+ n = round_up(cnt, 4);
+ tmpbuf = rtw_malloc(n);
+ if (!tmpbuf)
+ return -1;
+
+ err = sd_read(intfhdl, addr, n, tmpbuf);
+ if (!err)
+ memcpy(buf, tmpbuf, cnt);
+
+ kfree(tmpbuf);
+
+ return err;
+}
+
+/*
+ * Todo: align address to 4 bytes.
+ */
+s32 sdio_local_write(
+ struct adapter *adapter,
+ u32 addr,
+ u32 cnt,
+ u8 *buf
+)
+{
+ struct intf_hdl *intfhdl;
+ u8 mac_pwr_ctrl_on;
+ s32 err;
+ u8 *tmpbuf;
+
+ intfhdl = &adapter->iopriv.intf;
+
+ hal_sdio_get_cmd_addr_8723b(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
+
+ rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
+ if (
+ (!mac_pwr_ctrl_on) ||
+ (adapter_to_pwrctl(adapter)->fw_current_in_ps_mode)
+ )
+ return sd_cmd52_write(intfhdl, addr, cnt, buf);
+
+ tmpbuf = rtw_malloc(cnt);
+ if (!tmpbuf)
+ return -1;
+
+ memcpy(tmpbuf, buf, cnt);
+
+ err = sd_write(intfhdl, addr, cnt, tmpbuf);
+
+ kfree(tmpbuf);
+
+ return err;
+}
+
+u8 SdioLocalCmd52Read1Byte(struct adapter *adapter, u32 addr)
+{
+ u8 val = 0;
+ struct intf_hdl *intfhdl = &adapter->iopriv.intf;
+
+ hal_sdio_get_cmd_addr_8723b(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
+ sd_cmd52_read(intfhdl, addr, 1, &val);
+
+ return val;
+}
+
+static u16 sdio_local_cmd52_read2byte(struct adapter *adapter, u32 addr)
+{
+ __le16 val = 0;
+ struct intf_hdl *intfhdl = &adapter->iopriv.intf;
+
+ hal_sdio_get_cmd_addr_8723b(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
+ sd_cmd52_read(intfhdl, addr, 2, (u8 *)&val);
+
+ return le16_to_cpu(val);
+}
+
+static u32 sdio_local_cmd53_read4byte(struct adapter *adapter, u32 addr)
+{
+
+ u8 mac_pwr_ctrl_on;
+ u32 val = 0;
+ struct intf_hdl *intfhdl = &adapter->iopriv.intf;
+ __le32 le_tmp;
+
+ hal_sdio_get_cmd_addr_8723b(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
+ rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
+ if (!mac_pwr_ctrl_on || adapter_to_pwrctl(adapter)->fw_current_in_ps_mode) {
+ sd_cmd52_read(intfhdl, addr, 4, (u8 *)&le_tmp);
+ val = le32_to_cpu(le_tmp);
+ } else {
+ val = sd_read32(intfhdl, addr, NULL);
+ }
+ return val;
+}
+
+void SdioLocalCmd52Write1Byte(struct adapter *adapter, u32 addr, u8 v)
+{
+ struct intf_hdl *intfhdl = &adapter->iopriv.intf;
+
+ hal_sdio_get_cmd_addr_8723b(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
+ sd_cmd52_write(intfhdl, addr, 1, &v);
+}
+
+static void sdio_local_cmd52_write4byte(struct adapter *adapter, u32 addr, u32 v)
+{
+ struct intf_hdl *intfhdl = &adapter->iopriv.intf;
+ __le32 le_tmp;
+
+ hal_sdio_get_cmd_addr_8723b(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
+ le_tmp = cpu_to_le32(v);
+ sd_cmd52_write(intfhdl, addr, 4, (u8 *)&le_tmp);
+}
+
+static s32 read_interrupt_8723b_sdio(struct adapter *adapter, u32 *phisr)
+{
+ u32 hisr, himr;
+ u8 val8, hisr_len;
+
+ if (!phisr)
+ return false;
+
+ himr = GET_HAL_DATA(adapter)->sdio_himr;
+
+ /* decide how many bytes need to be read */
+ hisr_len = 0;
+ while (himr) {
+ hisr_len++;
+ himr >>= 8;
+ }
+
+ hisr = 0;
+ while (hisr_len != 0) {
+ hisr_len--;
+ val8 = SdioLocalCmd52Read1Byte(adapter, SDIO_REG_HISR + hisr_len);
+ hisr |= (val8 << (8 * hisr_len));
+ }
+
+ *phisr = hisr;
+
+ return true;
+}
+
+/* */
+/* Description: */
+/* Initialize SDIO Host Interrupt Mask configuration variables for future use. */
+/* */
+/* Assumption: */
+/* Using SDIO Local register ONLY for configuration. */
+/* */
+/* Created by Roger, 2011.02.11. */
+/* */
+void InitInterrupt8723BSdio(struct adapter *adapter)
+{
+ struct hal_com_data *haldata;
+
+ haldata = GET_HAL_DATA(adapter);
+ haldata->sdio_himr = (u32)(SDIO_HIMR_RX_REQUEST_MSK |
+ SDIO_HIMR_AVAL_MSK |
+ 0);
+}
+
+/* */
+/* Description: */
+/* Initialize System Host Interrupt Mask configuration variables for future use. */
+/* */
+/* Created by Roger, 2011.08.03. */
+/* */
+void InitSysInterrupt8723BSdio(struct adapter *adapter)
+{
+ struct hal_com_data *haldata;
+
+ haldata = GET_HAL_DATA(adapter);
+
+ haldata->SysIntrMask = (0);
+}
+
+/* */
+/* Description: */
+/* Enalbe SDIO Host Interrupt Mask configuration on SDIO local domain. */
+/* */
+/* Assumption: */
+/* 1. Using SDIO Local register ONLY for configuration. */
+/* 2. PASSIVE LEVEL */
+/* */
+/* Created by Roger, 2011.02.11. */
+/* */
+void EnableInterrupt8723BSdio(struct adapter *adapter)
+{
+ struct hal_com_data *haldata;
+ __le32 himr;
+ u32 tmp;
+
+ haldata = GET_HAL_DATA(adapter);
+
+ himr = cpu_to_le32(haldata->sdio_himr);
+ sdio_local_write(adapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
+
+ /* Update current system IMR settings */
+ tmp = rtw_read32(adapter, REG_HSIMR);
+ rtw_write32(adapter, REG_HSIMR, tmp | haldata->SysIntrMask);
+
+ /* */
+ /* <Roger_Notes> There are some C2H CMDs have been sent before system interrupt is enabled, e.g., C2H, CPWM. */
+ /* So we need to clear all C2H events that FW has notified, otherwise FW won't schedule any commands anymore. */
+ /* 2011.10.19. */
+ /* */
+ rtw_write8(adapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
+}
+
+/* */
+/* Description: */
+/* Disable SDIO Host IMR configuration to mask unnecessary interrupt service. */
+/* */
+/* Assumption: */
+/* Using SDIO Local register ONLY for configuration. */
+/* */
+/* Created by Roger, 2011.02.11. */
+/* */
+void DisableInterrupt8723BSdio(struct adapter *adapter)
+{
+ __le32 himr;
+
+ himr = cpu_to_le32(SDIO_HIMR_DISABLED);
+ sdio_local_write(adapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
+}
+
+/* */
+/* Description: */
+/* Using 0x100 to check the power status of FW. */
+/* */
+/* Assumption: */
+/* Using SDIO Local register ONLY for configuration. */
+/* */
+/* Created by Isaac, 2013.09.10. */
+/* */
+u8 CheckIPSStatus(struct adapter *adapter)
+{
+ if (rtw_read8(adapter, 0x100) == 0xEA)
+ return true;
+ else
+ return false;
+}
+
+static struct recv_buf *sd_recv_rxfifo(struct adapter *adapter, u32 size)
+{
+ u32 readsize, ret;
+ u8 *readbuf;
+ struct recv_priv *recv_priv;
+ struct recv_buf *recvbuf;
+
+ /* Patch for some SDIO Host 4 bytes issue */
+ /* ex. RK3188 */
+ readsize = round_up(size, 4);
+
+ /* 3 1. alloc recvbuf */
+ recv_priv = &adapter->recvpriv;
+ recvbuf = rtw_dequeue_recvbuf(&recv_priv->free_recv_buf_queue);
+ if (!recvbuf) {
+ netdev_err(adapter->pnetdev, "%s: alloc recvbuf FAIL!\n",
+ __func__);
+ return NULL;
+ }
+
+ /* 3 2. alloc skb */
+ if (!recvbuf->pskb) {
+ SIZE_PTR tmpaddr = 0;
+ SIZE_PTR alignment = 0;
+
+ recvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
+ if (!recvbuf->pskb)
+ return NULL;
+
+ recvbuf->pskb->dev = adapter->pnetdev;
+
+ tmpaddr = (SIZE_PTR)recvbuf->pskb->data;
+ alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1);
+ skb_reserve(recvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
+ }
+
+ /* 3 3. read data from rxfifo */
+ readbuf = recvbuf->pskb->data;
+ ret = sdio_read_port(&adapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, readbuf);
+ if (ret == _FAIL)
+ return NULL;
+
+ /* 3 4. init recvbuf */
+ recvbuf->len = size;
+ recvbuf->phead = recvbuf->pskb->head;
+ recvbuf->pdata = recvbuf->pskb->data;
+ skb_set_tail_pointer(recvbuf->pskb, size);
+ recvbuf->ptail = skb_tail_pointer(recvbuf->pskb);
+ recvbuf->pend = skb_end_pointer(recvbuf->pskb);
+
+ return recvbuf;
+}
+
+static void sd_rxhandler(struct adapter *adapter, struct recv_buf *recvbuf)
+{
+ struct recv_priv *recv_priv;
+ struct __queue *pending_queue;
+
+ recv_priv = &adapter->recvpriv;
+ pending_queue = &recv_priv->recv_buf_pending_queue;
+
+ /* 3 1. enqueue recvbuf */
+ rtw_enqueue_recvbuf(recvbuf, pending_queue);
+
+ /* 3 2. schedule tasklet */
+ tasklet_schedule(&recv_priv->recv_tasklet);
+}
+
+void sd_int_dpc(struct adapter *adapter)
+{
+ struct hal_com_data *hal;
+ struct dvobj_priv *dvobj;
+ struct intf_hdl *intfhdl = &adapter->iopriv.intf;
+ struct pwrctrl_priv *pwrctl;
+
+ hal = GET_HAL_DATA(adapter);
+ dvobj = adapter_to_dvobj(adapter);
+ pwrctl = dvobj_to_pwrctl(dvobj);
+
+ if (hal->sdio_hisr & SDIO_HISR_AVAL) {
+ u8 freepage[4];
+
+ _sdio_local_read(adapter, SDIO_REG_FREE_TXPG, 4, freepage);
+ complete(&(adapter->xmitpriv.xmit_comp));
+ }
+
+ if (hal->sdio_hisr & SDIO_HISR_CPWM1) {
+ del_timer_sync(&(pwrctl->pwr_rpwm_timer));
+
+ SdioLocalCmd52Read1Byte(adapter, SDIO_REG_HCPWM1_8723B);
+
+ _set_workitem(&(pwrctl->cpwm_event));
+ }
+
+ if (hal->sdio_hisr & SDIO_HISR_TXERR) {
+ u8 *status;
+ u32 addr;
+
+ status = rtw_malloc(4);
+ if (status) {
+ addr = REG_TXDMA_STATUS;
+ hal_sdio_get_cmd_addr_8723b(adapter, WLAN_IOREG_DEVICE_ID, addr, &addr);
+ _sd_read(intfhdl, addr, 4, status);
+ _sd_write(intfhdl, addr, 4, status);
+ kfree(status);
+ }
+ }
+
+ if (hal->sdio_hisr & SDIO_HISR_C2HCMD) {
+ struct c2h_evt_hdr_88xx *c2h_evt;
+
+ c2h_evt = rtw_zmalloc(16);
+ if (c2h_evt) {
+ if (c2h_evt_read_88xx(adapter, (u8 *)c2h_evt) == _SUCCESS) {
+ if (c2h_id_filter_ccx_8723b((u8 *)c2h_evt)) {
+ /* Handle CCX report here */
+ rtw_hal_c2h_handler(adapter, (u8 *)c2h_evt);
+ kfree(c2h_evt);
+ } else {
+ rtw_c2h_wk_cmd(adapter, (u8 *)c2h_evt);
+ }
+ } else {
+ kfree(c2h_evt);
+ }
+ } else {
+ /* Error handling for malloc fail */
+ rtw_cbuf_push(adapter->evtpriv.c2h_queue, NULL);
+ _set_workitem(&adapter->evtpriv.c2h_wk);
+ }
+ }
+
+ if (hal->sdio_hisr & SDIO_HISR_RX_REQUEST) {
+ struct recv_buf *recvbuf;
+ int alloc_fail_time = 0;
+ u32 hisr;
+
+ hal->sdio_hisr ^= SDIO_HISR_RX_REQUEST;
+ do {
+ hal->SdioRxFIFOSize = sdio_local_cmd52_read2byte(adapter, SDIO_REG_RX0_REQ_LEN);
+ if (hal->SdioRxFIFOSize != 0) {
+ recvbuf = sd_recv_rxfifo(adapter, hal->SdioRxFIFOSize);
+ if (recvbuf)
+ sd_rxhandler(adapter, recvbuf);
+ else {
+ alloc_fail_time++;
+ if (alloc_fail_time >= 10)
+ break;
+ }
+ hal->SdioRxFIFOSize = 0;
+ } else
+ break;
+
+ hisr = 0;
+ read_interrupt_8723b_sdio(adapter, &hisr);
+ hisr &= SDIO_HISR_RX_REQUEST;
+ if (!hisr)
+ break;
+ } while (1);
+ }
+}
+
+void sd_int_hdl(struct adapter *adapter)
+{
+ struct hal_com_data *hal;
+
+ if (
+ (adapter->bDriverStopped) || (adapter->bSurpriseRemoved)
+ )
+ return;
+
+ hal = GET_HAL_DATA(adapter);
+
+ hal->sdio_hisr = 0;
+ read_interrupt_8723b_sdio(adapter, &hal->sdio_hisr);
+
+ if (hal->sdio_hisr & hal->sdio_himr) {
+ u32 v32;
+
+ hal->sdio_hisr &= hal->sdio_himr;
+
+ /* clear HISR */
+ v32 = hal->sdio_hisr & MASK_SDIO_HISR_CLEAR;
+ if (v32)
+ sdio_local_cmd52_write4byte(adapter, SDIO_REG_HISR, v32);
+
+ sd_int_dpc(adapter);
+ }
+}
+
+/* */
+/* Description: */
+/* Query SDIO Local register to query current the number of Free TxPacketBuffer page. */
+/* */
+/* Assumption: */
+/* 1. Running at PASSIVE_LEVEL */
+/* 2. RT_TX_SPINLOCK is NOT acquired. */
+/* */
+/* Created by Roger, 2011.01.28. */
+/* */
+u8 HalQueryTxBufferStatus8723BSdio(struct adapter *adapter)
+{
+ struct hal_com_data *hal;
+ u32 numof_free_page;
+
+ hal = GET_HAL_DATA(adapter);
+
+ numof_free_page = sdio_local_cmd53_read4byte(adapter, SDIO_REG_FREE_TXPG);
+
+ memcpy(hal->SdioTxFIFOFreePage, &numof_free_page, 4);
+
+ return true;
+}
+
+/* */
+/* Description: */
+/* Query SDIO Local register to get the current number of TX OQT Free Space. */
+/* */
+void HalQueryTxOQTBufferStatus8723BSdio(struct adapter *adapter)
+{
+ struct hal_com_data *haldata = GET_HAL_DATA(adapter);
+
+ haldata->SdioTxOQTFreeSpace = SdioLocalCmd52Read1Byte(adapter, SDIO_REG_OQT_FREE_PG);
+}
+
+