diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:49:45 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:49:45 +0000 |
commit | 2c3c1048746a4622d8c89a29670120dc8fab93c4 (patch) | |
tree | 848558de17fb3008cdf4d861b01ac7781903ce39 /drivers/staging/rtl8723bs/hal | |
parent | Initial commit. (diff) | |
download | linux-upstream.tar.xz linux-upstream.zip |
Adding upstream version 6.1.76.upstream/6.1.76upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
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); +} + + |