1780 lines
55 KiB
C
Executable File
1780 lines
55 KiB
C
Executable File
/*
|
|
* Routines to access hardware
|
|
*
|
|
* $Id: 8188e_hw.c,v 1.1 2012/05/16 13:21:01 jimmylin Exp $
|
|
*
|
|
* Copyright (c) 2012 Realtek Semiconductor Corp.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
|
|
#ifdef __ECOS
|
|
#include <cyg/io/eth/rltk/819x/wrapper/sys_support.h>
|
|
#include <cyg/io/eth/rltk/819x/wrapper/skbuff.h>
|
|
#include <cyg/io/eth/rltk/819x/wrapper/timer.h>
|
|
#include <cyg/io/eth/rltk/819x/wrapper/wrapper.h>
|
|
#endif
|
|
|
|
|
|
#define _8188E_HW_C_
|
|
|
|
#include "8192cd_cfg.h"
|
|
#include "8192cd.h"
|
|
#include "8192cd_util.h"
|
|
|
|
#include "8192c_reg.h"
|
|
#include "8188e_reg.h"
|
|
|
|
#ifdef CONFIG_RTL_88E_SUPPORT
|
|
|
|
#ifdef TXREPORT
|
|
#ifdef __KERNEL__
|
|
#include <linux/kernel.h>
|
|
#endif
|
|
#include "8192cd_debug.h"
|
|
#include "8192cd_headers.h"
|
|
|
|
|
|
|
|
void RTL8188E_EnableTxReport(struct rtl8192cd_priv *priv)
|
|
{
|
|
DEBUG_INFO("%s %d\n", __FUNCTION__, __LINE__);
|
|
RTL_W16(REG_88E_TXRPT_TIM, 0xffff); /* unit: 32us */
|
|
RTL_W32(REG_88E_TXRPT_CTRL, TXRPT_CTRL_88E_TXRPT_EN);
|
|
}
|
|
|
|
|
|
void RTL8188E_DisableTxReport(struct rtl8192cd_priv *priv)
|
|
{
|
|
DEBUG_INFO("%s %d\n", __FUNCTION__, __LINE__);
|
|
RTL_W32(REG_88E_TXRPT_CTRL, 0);
|
|
RTL_W16(REG_88E_TXRPT_TIM, 0);
|
|
}
|
|
|
|
|
|
void RTL8188E_ResumeTxReport(struct rtl8192cd_priv *priv)
|
|
{
|
|
DEBUG_INFO("%s %d\n", __FUNCTION__, __LINE__);
|
|
RTL_W32(REG_88E_TXRPT_CTRL, RTL_R32(REG_88E_TXRPT_CTRL) | TXRPT_CTRL_88E_TXRPT_TIM_EN);
|
|
}
|
|
|
|
|
|
void RTL8188E_SuspendTxReport(struct rtl8192cd_priv *priv)
|
|
{
|
|
DEBUG_INFO("%s %d\n", __FUNCTION__, __LINE__);
|
|
RTL_W32(REG_88E_TXRPT_CTRL, RTL_R32(REG_88E_TXRPT_CTRL) & ~TXRPT_CTRL_88E_TXRPT_TIM_EN);
|
|
}
|
|
|
|
|
|
static unsigned int findout_max_macid(struct rtl8192cd_priv *priv)
|
|
{
|
|
struct stat_info *pstat;
|
|
struct list_head *phead, *plist;
|
|
unsigned int max_macid = 0;
|
|
#ifdef SMP_SYNC
|
|
unsigned long flags = 0;
|
|
#endif
|
|
|
|
phead = &priv->asoc_list;
|
|
|
|
SMP_LOCK_ASOC_LIST(flags);
|
|
|
|
plist = phead->next;
|
|
while(plist != phead) {
|
|
pstat = list_entry(plist, struct stat_info, asoc_list);
|
|
plist = plist->next;
|
|
|
|
if(pstat->sta_in_firmware != 1)
|
|
continue;
|
|
|
|
if (REMAP_AID(pstat) > max_macid)
|
|
max_macid = REMAP_AID(pstat);
|
|
}
|
|
|
|
SMP_UNLOCK_ASOC_LIST(flags);
|
|
|
|
return max_macid;
|
|
}
|
|
|
|
#ifdef RATEADAPTIVE_BY_ODM
|
|
void RTL8188E_SetStationTxRateInfo(PDM_ODM_T pDM_Odm, PODM_RA_INFO_T pRAInfo, int MacID)
|
|
{
|
|
struct rtl8192cd_priv *priv = pDM_Odm->priv;
|
|
PSTA_INFO_T pstat = pDM_Odm->pODM_StaInfo[MacID];
|
|
#if defined(UNIVERSAL_REPEATER) || defined(MBSSID)
|
|
struct aid_obj *aidobj;
|
|
#endif
|
|
|
|
if( !MacID || !pstat)
|
|
return;
|
|
|
|
#if defined(UNIVERSAL_REPEATER) || defined(MBSSID)
|
|
aidobj = container_of(pstat, struct aid_obj, station);
|
|
priv = aidobj->priv;
|
|
#endif
|
|
|
|
if (priv->pmib->dot11StationConfigEntry.autoRate) {
|
|
if (pRAInfo->RateSGI)
|
|
pstat->ht_current_tx_info |= TX_USE_SHORT_GI;
|
|
else
|
|
pstat->ht_current_tx_info &= ~TX_USE_SHORT_GI;
|
|
|
|
if (pstat->ht_cap_len) {
|
|
if (priv->pshare->is_40m_bw && (pstat->tx_bw == HT_CHANNEL_WIDTH_20_40))
|
|
pstat->ht_current_tx_info |= TX_USE_40M_MODE;
|
|
else
|
|
pstat->ht_current_tx_info &= ~TX_USE_40M_MODE;
|
|
}
|
|
|
|
if ((pRAInfo->DecisionRate&0x3f) < 12)
|
|
pstat->current_tx_rate = dot11_rate_table[pRAInfo->DecisionRate&0x3f];
|
|
else if ((pRAInfo->DecisionRate&0x3f) <= 27)
|
|
pstat->current_tx_rate = HT_RATE_ID|((pRAInfo->DecisionRate&0x3f) -12);
|
|
else
|
|
DEBUG_WARN("%s %d, DecisionRate mismatched as 0x%02x\n", __FUNCTION__, __LINE__, pRAInfo->DecisionRate);
|
|
|
|
priv->pshare->current_tx_rate = pstat->current_tx_rate;
|
|
priv->pshare->ht_current_tx_info = pstat->ht_current_tx_info;
|
|
}
|
|
}
|
|
#else
|
|
static void RTL8188E_SetStationTxRateInfo(struct rtl8192cd_priv *priv, PSTATION_RA_INFO pRaInfo)
|
|
{
|
|
if (pRaInfo->RateSGI)
|
|
pRaInfo->pstat->ht_current_tx_info |= TX_USE_SHORT_GI;
|
|
else
|
|
pRaInfo->pstat->ht_current_tx_info &= ~TX_USE_SHORT_GI;
|
|
|
|
if (pRaInfo->pstat->ht_cap_len) {
|
|
if (priv->pshare->is_40m_bw && (pRaInfo->pstat->tx_bw == HT_CHANNEL_WIDTH_20_40))
|
|
pRaInfo->pstat->ht_current_tx_info |= TX_USE_40M_MODE;
|
|
else
|
|
pRaInfo->pstat->ht_current_tx_info &= ~TX_USE_40M_MODE;
|
|
}
|
|
|
|
if ((pRaInfo->DecisionRate&0x3f) < 12)
|
|
pRaInfo->pstat->current_tx_rate = dot11_rate_table[pRaInfo->DecisionRate];
|
|
else if ((pRaInfo->DecisionRate&0x3f) <= 27)
|
|
pRaInfo->pstat->current_tx_rate = HT_RATE_ID|((pRaInfo->DecisionRate&0x3f) -12);
|
|
else
|
|
DEBUG_WARN("%s %d, DecisionRate mismatched as 0x%02x\n", __FUNCTION__, __LINE__, pRaInfo->DecisionRate);
|
|
|
|
priv->pshare->current_tx_rate = pRaInfo->pstat->current_tx_rate;
|
|
priv->pshare->ht_current_tx_info = pRaInfo->pstat->ht_current_tx_info;
|
|
}
|
|
|
|
#endif
|
|
|
|
void RTL8188E_AssignTxReportMacId(struct rtl8192cd_priv *priv)
|
|
{
|
|
struct rtl8192cd_priv *tmp_root_priv = GET_ROOT(priv);
|
|
unsigned int max_macid = 0;
|
|
#ifdef MBSSID
|
|
unsigned int i = 0;
|
|
#endif
|
|
#if defined(UNIVERSAL_REPEATER) || defined(MBSSID)
|
|
unsigned int temp_macid = 0;
|
|
#endif
|
|
|
|
/* find out the largest macid */
|
|
max_macid = findout_max_macid(tmp_root_priv);
|
|
#ifdef UNIVERSAL_REPEATER
|
|
if (GET_VXD_PRIV(tmp_root_priv) && netif_running(GET_VXD_PRIV(tmp_root_priv)->dev)) {
|
|
temp_macid = findout_max_macid(GET_VXD_PRIV(tmp_root_priv));
|
|
if (temp_macid > max_macid)
|
|
max_macid = temp_macid;
|
|
}
|
|
#endif
|
|
#ifdef MBSSID
|
|
if (tmp_root_priv->pmib->miscEntry.vap_enable) {
|
|
for (i=0; i<RTL8192CD_NUM_VWLAN; i++) {
|
|
if (IS_DRV_OPEN(tmp_root_priv->pvap_priv[i])) {
|
|
temp_macid = findout_max_macid(tmp_root_priv->pvap_priv[i]);
|
|
if (temp_macid > max_macid)
|
|
max_macid = temp_macid;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* assign new macid for tx report setting iff it is different from the previous one */
|
|
if (max_macid && (priv->pshare->txRptMacid != max_macid)) {
|
|
RTL_W32(REG_88E_TXRPT_CTRL, (RTL_R32(REG_88E_TXRPT_CTRL)
|
|
& (~(TXRPT_CTRL_88E_RPT_MACID_Mask << TXRPT_CTRL_88E_RPT_MACID_SHIFT)))
|
|
| (((max_macid+1) & TXRPT_CTRL_88E_RPT_MACID_Mask) << TXRPT_CTRL_88E_RPT_MACID_SHIFT)
|
|
#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)
|
|
| TXRPT_CTRL_88E_TXRPT_TIM_EN
|
|
#endif
|
|
);
|
|
|
|
DEBUG_INFO("%s %d, preTxRptMacid: %d, newTxRptMacid: %d\n", __FUNCTION__, __LINE__, priv->pshare->txRptMacid, max_macid);
|
|
priv->pshare->txRptMacid = max_macid;
|
|
}
|
|
}
|
|
|
|
#ifdef DETECT_STA_EXISTANCE
|
|
void RTL8188E_DetectSTAExistance(struct rtl8192cd_priv *priv, struct tx_rpt *report, struct stat_info *pstat)
|
|
{
|
|
const unsigned int txFailSecThr= 3; // threshold of Tx Fail Time (in second)
|
|
|
|
if(OPMODE & WIFI_STATION_STATE)
|
|
return;
|
|
|
|
if (report->txok)
|
|
{ // Reset Counter
|
|
pstat->tx_conti_fail_cnt = 0;
|
|
pstat->tx_last_good_time = priv->up_time;
|
|
if (pstat->leave!= 0) {
|
|
pstat->leave = 0;
|
|
RTL8188E_MACID_NOLINK(priv, 0, REMAP_AID(pstat));
|
|
}
|
|
}
|
|
else if (report->txfail)
|
|
{
|
|
if (pstat->leave)
|
|
return;
|
|
|
|
pstat->tx_conti_fail_cnt += report->txfail;
|
|
if((pstat->tx_conti_fail_cnt >= priv->pshare->rf_ft_var.max_pkt_fail) ||
|
|
(pstat->tx_conti_fail_cnt >= priv->pshare->rf_ft_var.min_pkt_fail && priv->up_time >= (pstat->tx_last_good_time+txFailSecThr) )
|
|
) {
|
|
DEBUG_INFO("sta aid:%d leave\n", pstat->aid);
|
|
++(pstat->leave);
|
|
RTL8188E_MACID_NOLINK(priv, 1, REMAP_AID(pstat));
|
|
#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)
|
|
free_sta_tx_skb(priv, pstat);
|
|
#endif
|
|
|
|
// Reset Counter
|
|
pstat->tx_conti_fail_cnt = 0;
|
|
pstat->tx_last_good_time = priv->up_time;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
#ifndef RATEADAPTIVE_BY_ODM
|
|
|
|
void RTL8188E_TxReportHandler(struct rtl8192cd_priv *priv, struct sk_buff *pskb, unsigned int bitmapLowByte,
|
|
unsigned int bitmapHighByte, struct rx_desc* pdesc)
|
|
{
|
|
PSTATION_RA_INFO pRaInfo = NULL;
|
|
unsigned char* Buffer= NULL;
|
|
unsigned char i = 0;
|
|
unsigned int offset = 0;
|
|
unsigned short minRptTime = 0xffff /*0x927c*/;
|
|
struct rx_frinfo *pfrinfo = get_pfrinfo(pskb);
|
|
|
|
struct rtl8192cd_priv *priv_root = priv;
|
|
struct stat_info *pstat;
|
|
struct tx_rpt rpt1;
|
|
|
|
for(i = 1; i <= priv->pshare->txRptMacid; i++) {
|
|
if (i >= 32) {
|
|
if (!(bitmapHighByte & BIT(i-32)))
|
|
continue;
|
|
} else {
|
|
if (!(bitmapLowByte & BIT(i)))
|
|
continue;
|
|
}
|
|
|
|
do {
|
|
pstat = get_macidinfo(priv_root, i);
|
|
if (pstat) {
|
|
priv = priv_root;
|
|
break;
|
|
}
|
|
#ifdef UNIVERSAL_REPEATER
|
|
if (IS_DRV_OPEN(GET_VXD_PRIV(priv_root))) {
|
|
pstat = get_macidinfo(GET_VXD_PRIV(priv_root), i);
|
|
if (pstat) {
|
|
priv = GET_VXD_PRIV(priv_root);
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
#ifdef MBSSID
|
|
if (priv_root->pmib->miscEntry.vap_enable) {
|
|
int idx;
|
|
for (idx=0; idx<RTL8192CD_NUM_VWLAN; idx++) {
|
|
if (IS_DRV_OPEN(priv_root->pvap_priv[idx])) {
|
|
pstat = get_macidinfo(priv_root->pvap_priv[idx], i);
|
|
if (pstat) {
|
|
priv = priv_root->pvap_priv[idx];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
} while (0);
|
|
|
|
if (NULL == pstat)
|
|
continue;
|
|
|
|
pRaInfo = &(priv_root->pshare->RaInfo[pstat->aid]);
|
|
if (!pRaInfo->pstat)
|
|
continue;
|
|
|
|
offset = i << 3; // Start of entry RA data
|
|
DEBUG_INFO("%s %d, MacId=%d offset=%d\n", __FUNCTION__, __LINE__, i, offset);
|
|
|
|
if(offset + 8 > pfrinfo->pktlen) {
|
|
DEBUG_WARN("%s %d, offset + 8 > pfrinfo->pktlen, break!!\n", __FUNCTION__, __LINE__);
|
|
break;
|
|
} else {
|
|
Buffer = pskb->data + offset;
|
|
if (!Buffer[0] && !Buffer[1] && !Buffer[2] && !Buffer[3] && !Buffer[4] && !Buffer[5] && !Buffer[6] && !Buffer[7]) {
|
|
printk("\n%s %d, rpt but not update for aid:%d\n", __FUNCTION__, __LINE__, i);
|
|
#ifdef CONFIG_PCI_HCI
|
|
RTL_W8(0x3a, 0xff); /* for CATC triggering only, meaningless */
|
|
#endif
|
|
printk("=====rxdesc=====\n");
|
|
printk("D0:0x%08x, D1:0x%08x, D2:0x%08x, D3:0x%08x, \nD4:0x%08x, D5:0x%08x",
|
|
get_desc(pdesc->Dword0), get_desc(pdesc->Dword1), get_desc(pdesc->Dword2), get_desc(pdesc->Dword3),
|
|
get_desc(pdesc->Dword4), get_desc(pdesc->Dword5));
|
|
#ifdef CONFIG_PCI_HCI
|
|
printk(", D6:0x%08x, D7:0x%08x", get_desc(pdesc->Dword6), get_desc(pdesc->Dword7));
|
|
#endif
|
|
printk("\n=====rxdesc=====\n");
|
|
printk("=====buffer=====\n");
|
|
/* printk("B0:0x%08x, B1:0x%08x, B2:0x%08x, B3:0x%08x\n",
|
|
(unsigned int)(pskb->data[0]), (unsigned int)(pskb->data[4]), (unsigned int)(pskb->data[8]), (unsigned int)(pskb->data[12]));*/
|
|
printk("B0:0x%02x, B1:0x%02x, B2:0x%02x, B3:0x%02x, B4:0x%02x, B5:0x%02x, B6:0x%02x, B7:0x%02x, B8:0x%02x, B9:0x%02x, B10:0x%02x, B11:0x%02x, B12:0x%02x, B13:0x%02x, B14:0x%02x, B15:0x%02x\n",
|
|
pskb->data[0], pskb->data[1], pskb->data[2], pskb->data[3],
|
|
pskb->data[4], pskb->data[5], pskb->data[6], pskb->data[7],
|
|
pskb->data[8], pskb->data[9], pskb->data[10], pskb->data[11],
|
|
pskb->data[12], pskb->data[13], pskb->data[14], pskb->data[15]);
|
|
printk("=====buffer=====\n\n");
|
|
continue;
|
|
}
|
|
|
|
pRaInfo->RTY[0] = (unsigned short)(Buffer[1] << 8 | Buffer[0]);
|
|
pRaInfo->RTY[1] = Buffer[2];
|
|
pRaInfo->RTY[2] = Buffer[3];
|
|
pRaInfo->RTY[3] = Buffer[4];
|
|
pRaInfo->RTY[4] = Buffer[5];
|
|
pRaInfo->DROP = Buffer[6];
|
|
|
|
pRaInfo->TOTAL = pRaInfo->RTY[0] + pRaInfo->RTY[1] + pRaInfo->RTY[2] + pRaInfo->RTY[3]
|
|
+ pRaInfo->RTY[4] + pRaInfo->DROP;
|
|
|
|
DEBUG_INFO("%s %d, macid %d R0=%d R1=%d R2=%d R3=%d R4=%d D0=%d Total=%d, HB: 0x%08x LB: 0x%08x vld_hi:0x%08x, vld_lo:0x%08x\n",
|
|
__FUNCTION__, __LINE__, i,
|
|
pRaInfo->RTY[0],
|
|
pRaInfo->RTY[1],
|
|
pRaInfo->RTY[2],
|
|
pRaInfo->RTY[3],
|
|
pRaInfo->RTY[4],
|
|
pRaInfo->DROP,
|
|
pRaInfo->TOTAL,
|
|
(unsigned int)(Buffer[7] << 24 | Buffer[6]<<16|Buffer[5] << 8 | Buffer[4]),
|
|
(unsigned int)(Buffer[3] << 24 | Buffer[2]<<16|Buffer[1] << 8 | Buffer[0]),
|
|
bitmapHighByte, bitmapLowByte);
|
|
|
|
if (priv->pmib->dot11StationConfigEntry.autoRate) {
|
|
RateDecision(priv, pRaInfo);
|
|
RTL8188E_SetStationTxRateInfo(priv, pRaInfo);
|
|
}
|
|
|
|
rpt1.macid = i;
|
|
rpt1.txok = pRaInfo->RTY[0] + pRaInfo->RTY[1] + pRaInfo->RTY[2] + pRaInfo->RTY[3] + pRaInfo->RTY[4];
|
|
rpt1.txfail = pRaInfo->DROP;
|
|
_txrpt_handler(priv, pstat, &rpt1);
|
|
}
|
|
|
|
if(minRptTime > pRaInfo->RptTime)
|
|
minRptTime = pRaInfo->RptTime;
|
|
}
|
|
|
|
if (minRptTime != 0xffff) {
|
|
#if defined(CONFIG_PCI_HCI)
|
|
RTL_W16(REG_88E_TXRPT_TIM, minRptTime);
|
|
#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)
|
|
notify_tx_report_interval_change(priv, minRptTime);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
void RTL8188E_SetTxReportTimeByRA(struct rtl8192cd_priv *priv, int extend)
|
|
{
|
|
// extern unsigned short DynamicTxRPTTiming[];
|
|
extern unsigned char TxRPTTiming_idx;
|
|
|
|
// unsigned short WriteTxRPTTiming;
|
|
unsigned char idx;
|
|
|
|
idx=TxRPTTiming_idx;
|
|
if (extend==0) { // back to default timing
|
|
idx=1; //400ms
|
|
} else if (extend==1) {// increase the timing
|
|
idx+=1;
|
|
if (idx>5)
|
|
idx=5;
|
|
} else if (extend==2) {// decrease the timing
|
|
if(idx!=0)
|
|
idx-=1;
|
|
}
|
|
// WriteTxRPTTiming=DynamicTxRPTTiming[idx];
|
|
TxRPTTiming_idx=idx;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef CONFIG_PCI_HCI
|
|
static inline
|
|
#endif
|
|
void __RTL8188E_MACID_NOLINK(struct rtl8192cd_priv *priv, unsigned int nolink, unsigned int aid)
|
|
{
|
|
if (nolink) {
|
|
if (aid > 31)
|
|
RTL_W32(REG_88E_MACID_NOLINK+4, RTL_R32(REG_88E_MACID_NOLINK+4) | BIT(aid -31));
|
|
else
|
|
RTL_W32(REG_88E_MACID_NOLINK, RTL_R32(REG_88E_MACID_NOLINK) | BIT(aid));
|
|
} else {
|
|
if (aid > 31)
|
|
RTL_W32(REG_88E_MACID_NOLINK+4, RTL_R32(REG_88E_MACID_NOLINK+4) & ~BIT(aid-31));
|
|
else
|
|
RTL_W32(REG_88E_MACID_NOLINK, RTL_R32(REG_88E_MACID_NOLINK) & ~BIT(aid));
|
|
}
|
|
}
|
|
|
|
void RTL8188E_MACID_NOLINK(struct rtl8192cd_priv *priv, unsigned int nolink, unsigned int aid)
|
|
{
|
|
if (!priv->pshare->rf_ft_var.disable_pkt_nolink) {
|
|
#if defined(CONFIG_PCI_HCI)
|
|
__RTL8188E_MACID_NOLINK(priv, nolink, aid);
|
|
#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)
|
|
notify_macid_no_link_change(priv, aid, nolink);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#ifdef CONFIG_PCI_HCI
|
|
static inline
|
|
#endif
|
|
void __RTL8188E_MACID_PAUSE(struct rtl8192cd_priv *priv, unsigned int pause, unsigned int aid)
|
|
{
|
|
if (pause) {
|
|
if (aid > 31)
|
|
RTL_W32(REG_88E_MACID_PAUSE+4, RTL_R32(REG_88E_MACID_PAUSE+4) | BIT(aid -31));
|
|
else
|
|
RTL_W32(REG_88E_MACID_PAUSE, RTL_R32(REG_88E_MACID_PAUSE) | BIT(aid));
|
|
} else {
|
|
if (aid > 31)
|
|
RTL_W32(REG_88E_MACID_PAUSE+4, RTL_R32(REG_88E_MACID_PAUSE+4) & ~BIT(aid -31));
|
|
else
|
|
RTL_W32(REG_88E_MACID_PAUSE, RTL_R32(REG_88E_MACID_PAUSE) & ~BIT(aid));
|
|
}
|
|
}
|
|
|
|
void RTL8188E_MACID_PAUSE(struct rtl8192cd_priv *priv, unsigned int pause, unsigned int aid)
|
|
{
|
|
if (!priv->pshare->rf_ft_var.disable_pkt_pause) {
|
|
#if defined(CONFIG_PCI_HCI)
|
|
__RTL8188E_MACID_PAUSE(priv, pause, aid);
|
|
#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)
|
|
notify_macid_pause_change(priv, aid, pause);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef SUPPORT_RTL8188E_TC
|
|
void check_RTL8188E_testChip(struct rtl8192cd_priv *priv)
|
|
{
|
|
if (!priv->pshare->rtl8188e_testchip_checked) {
|
|
if (RTL_R8(AFE_XTAL_CTRL+3) == 0x3F)
|
|
priv->pshare->version_id |= 0x100;
|
|
|
|
priv->pshare->rtl8188e_testchip_checked++;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifndef CALIBRATE_BY_ODM
|
|
|
|
|
|
#define IQK_DELAY_TIME_88E 10
|
|
|
|
#define bRFRegOffsetMask 0xfffff
|
|
|
|
|
|
void _PHY_PathAStandBy(struct rtl8192cd_priv *priv)
|
|
{
|
|
PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0x0);
|
|
PHY_SetBBReg(priv, 0x840, bMaskDWord, 0x00010000);
|
|
PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0x808000);
|
|
}
|
|
|
|
void _PHY_PathAFillIQKMatrix(struct rtl8192cd_priv *priv, char bIQKOK, int result[][8], unsigned char final_candidate, char bTxOnly)
|
|
{
|
|
int Oldval_0, X, TX0_A, reg;
|
|
int Y, TX0_C;
|
|
|
|
if(final_candidate == 0xFF)
|
|
return;
|
|
|
|
else if(bIQKOK) {
|
|
Oldval_0 = (PHY_QueryBBReg(priv, 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(priv, rOFDM0_XATxIQImbalance, 0x3FF, TX0_A);
|
|
PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(31), ((X* Oldval_0>>7) & 0x1));
|
|
|
|
Y = result[final_candidate][1];
|
|
if ((Y & 0x00000200) != 0)
|
|
Y = Y | 0xFFFFFC00;
|
|
TX0_C = (Y * Oldval_0) >> 8;
|
|
PHY_SetBBReg(priv, rOFDM0_XCTxAFE, 0xF0000000, ((TX0_C&0x3C0)>>6));
|
|
PHY_SetBBReg(priv, rOFDM0_XATxIQImbalance, 0x003F0000, (TX0_C&0x3F));
|
|
PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(29), ((Y* Oldval_0>>7) & 0x1));
|
|
|
|
if(bTxOnly) {
|
|
// RTPRINT(FINIT, INIT_IQK, ("_PHY_PathAFillIQKMatrix only Tx OK\n"));
|
|
return;
|
|
}
|
|
|
|
reg = result[final_candidate][2];
|
|
if( RTL_ABS(reg ,0x100) >= 16)
|
|
reg = 0x100;
|
|
PHY_SetBBReg(priv, rOFDM0_XARxIQImbalance, 0x3FF, reg);
|
|
|
|
reg = result[final_candidate][3] & 0x3F;
|
|
PHY_SetBBReg(priv, rOFDM0_XARxIQImbalance, 0xFC00, reg);
|
|
|
|
reg = (result[final_candidate][3] >> 6) & 0xF;
|
|
PHY_SetBBReg(priv, 0xca0, 0xF0000000, reg);
|
|
}
|
|
}
|
|
|
|
|
|
void _PHY_PIModeSwitch(struct rtl8192cd_priv *priv, char PIMode)
|
|
{
|
|
unsigned int mode;
|
|
|
|
DEBUG_INFO("BB Switch to %s mode!\n", (PIMode ? "PI" : "SI"));
|
|
|
|
mode = PIMode ? 0x01000100 : 0x01000000;
|
|
PHY_SetBBReg(priv, rFPGA0_XA_HSSIParameter1, bMaskDWord, mode);
|
|
PHY_SetBBReg(priv, rFPGA0_XB_HSSIParameter1, bMaskDWord, mode);
|
|
}
|
|
|
|
|
|
//bit0 = 1 => Tx OK, bit1 = 1 => Rx OK
|
|
unsigned char phy_PathA_IQK_8188E(struct rtl8192cd_priv *priv, unsigned char configPathB)
|
|
{
|
|
unsigned int regEAC, regE94, regE9C, regEA4;
|
|
unsigned char result = 0x00;
|
|
|
|
DEBUG_INFO("Path A IQK!\n");
|
|
|
|
//path-A IQK setting
|
|
DEBUG_INFO("Path-A IQK setting!\n");
|
|
PHY_SetBBReg(priv, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c);
|
|
PHY_SetBBReg(priv, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c);
|
|
PHY_SetBBReg(priv, rTx_IQK_PI_A, bMaskDWord, 0x8214032a);
|
|
PHY_SetBBReg(priv, rRx_IQK_PI_A, bMaskDWord, 0x28160000);
|
|
|
|
//LO calibration setting
|
|
DEBUG_INFO("LO calibration setting!\n");
|
|
PHY_SetBBReg(priv, rIQK_AGC_Rsp, bMaskDWord, 0x00462911); //0x001028d1
|
|
|
|
//One shot, path A LOK & IQK
|
|
DEBUG_INFO("One shot, path A LOK & IQK!\n");
|
|
PHY_SetBBReg(priv, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
|
|
PHY_SetBBReg(priv, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
|
|
|
|
// delay x ms
|
|
DEBUG_INFO("Delay %d ms for One shot, path A LOK & IQK.\n", IQK_DELAY_TIME_88E);
|
|
delay_ms(IQK_DELAY_TIME_88E);
|
|
|
|
// Check failed
|
|
regEAC = PHY_QueryBBReg(priv, rRx_Power_After_IQK_A_2, bMaskDWord);
|
|
DEBUG_INFO("0xeac = 0x%x\n", regEAC);
|
|
regE94 = PHY_QueryBBReg(priv, rTx_Power_Before_IQK_A, bMaskDWord);
|
|
DEBUG_INFO("0xe94 = 0x%x\n", regE94);
|
|
regE9C= PHY_QueryBBReg(priv, rTx_Power_After_IQK_A, bMaskDWord);
|
|
DEBUG_INFO("0xe9c = 0x%x\n", regE9C);
|
|
regEA4= PHY_QueryBBReg(priv, rRx_Power_Before_IQK_A_2, bMaskDWord);
|
|
DEBUG_INFO("0xea4 = 0x%x\n", regEA4);
|
|
|
|
if(!(regEAC & BIT(28)) &&
|
|
(((regE94 & 0x03FF0000)>>16) != 0x142) &&
|
|
(((regE9C & 0x03FF0000)>>16) != 0x42) )
|
|
result |= 0x01;
|
|
else //if Tx not OK, ignore Rx
|
|
return result;
|
|
|
|
#if 0
|
|
if(!(regEAC & BIT27) && //if Tx is OK, check whether Rx is OK
|
|
(((regEA4 & 0x03FF0000)>>16) != 0x132) &&
|
|
(((regEAC & 0x03FF0000)>>16) != 0x36))
|
|
result |= 0x02;
|
|
else
|
|
RTPRINT(FINIT, INIT_IQK, ("Path A Rx IQK fail!!\n"));
|
|
#endif
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
//bit0 = 1 => Tx OK, bit1 = 1 => Rx OK
|
|
unsigned char phy_PathA_RxIQK(struct rtl8192cd_priv *priv, char configPathB)
|
|
{
|
|
int regEAC, regE94, regE9C, regEA4, u4tmp;
|
|
unsigned char result = 0x00;
|
|
|
|
DEBUG_INFO("Path A Rx IQK!\n");
|
|
|
|
//get TXIMR setting
|
|
//modify RXIQK mode table
|
|
DEBUG_INFO("Path-A Rx IQK modify RXIQK mode table!\n");
|
|
PHY_SetBBReg(priv, rFPGA0_IQK, 0xffffff00, 0);
|
|
PHY_SetRFReg(priv, RF_PATH_A, RF_WE_LUT, bRFRegOffsetMask, 0x800a0 );
|
|
PHY_SetRFReg(priv, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000 );
|
|
PHY_SetRFReg(priv, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f );
|
|
PHY_SetRFReg(priv, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf117B );
|
|
PHY_SetBBReg(priv, rFPGA0_IQK, 0xffffff00, 0x808000);
|
|
|
|
//IQK setting
|
|
PHY_SetBBReg(priv, rTx_IQK, bMaskDWord, 0x01007c00);
|
|
PHY_SetBBReg(priv, rRx_IQK, bMaskDWord, 0x81004800);
|
|
|
|
//path-A IQK setting
|
|
PHY_SetBBReg(priv, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c);
|
|
PHY_SetBBReg(priv, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c);
|
|
PHY_SetBBReg(priv, rTx_IQK_PI_A, bMaskDWord, 0x82160804);
|
|
PHY_SetBBReg(priv, rRx_IQK_PI_A, bMaskDWord, 0x28160000);
|
|
|
|
//LO calibration setting
|
|
DEBUG_INFO("LO calibration setting!\n");
|
|
PHY_SetBBReg(priv, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911); //0x0010a8d1
|
|
|
|
//One shot, path A LOK & IQK
|
|
DEBUG_INFO("One shot, path A LOK & IQK!\n");
|
|
PHY_SetBBReg(priv, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
|
|
PHY_SetBBReg(priv, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
|
|
|
|
// delay x ms
|
|
DEBUG_INFO("Delay %d ms for One shot, path A LOK & IQK.\n", IQK_DELAY_TIME_88E);
|
|
delay_ms(IQK_DELAY_TIME_88E);
|
|
|
|
// Check failed
|
|
regEAC = PHY_QueryBBReg(priv, rRx_Power_After_IQK_A_2, bMaskDWord);
|
|
DEBUG_INFO("0xeac = 0x%x\n", regEAC);
|
|
regE94 = PHY_QueryBBReg(priv, rTx_Power_Before_IQK_A, bMaskDWord);
|
|
DEBUG_INFO("0xe94 = 0x%x\n", regE94);
|
|
regE9C = PHY_QueryBBReg(priv, rTx_Power_After_IQK_A, bMaskDWord);
|
|
DEBUG_INFO("0xe9c = 0x%x\n", regE9C);
|
|
|
|
if(!(regEAC & BIT(28)) &&
|
|
(((regE94 & 0x03FF0000)>>16) != 0x142) &&
|
|
(((regE9C & 0x03FF0000)>>16) != 0x42) )
|
|
result |= 0x01;
|
|
else //if Tx not OK, ignore Rx
|
|
return result;
|
|
|
|
u4tmp = 0x80007C00 | (regE94&0x3FF0000) | ((regE9C&0x3FF0000) >> 16);
|
|
PHY_SetBBReg(priv, rTx_IQK, bMaskDWord, u4tmp);
|
|
DEBUG_INFO("0xe40 = 0x%x u4tmp = 0x%x \n", PHY_QueryBBReg(priv, rTx_IQK, bMaskDWord), u4tmp);
|
|
|
|
|
|
//RX IQK
|
|
//modify RXIQK mode table
|
|
DEBUG_INFO("Path-A Rx IQK modify RXIQK mode table 2!\n");
|
|
PHY_SetBBReg(priv, rFPGA0_IQK, 0xffffff00, 0);
|
|
PHY_SetRFReg(priv, RF_PATH_A, RF_WE_LUT, bRFRegOffsetMask, 0x800a0 );
|
|
PHY_SetRFReg(priv, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000 );
|
|
PHY_SetRFReg(priv, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f );
|
|
PHY_SetRFReg(priv, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7ffa );
|
|
PHY_SetBBReg(priv, rFPGA0_IQK, 0xffffff00, 0x808000);
|
|
|
|
//IQK setting
|
|
PHY_SetBBReg(priv, rRx_IQK, bMaskDWord, 0x01004800);
|
|
|
|
//path-A IQK setting
|
|
PHY_SetBBReg(priv, rTx_IQK_Tone_A, bMaskDWord, 0x30008c1c);
|
|
PHY_SetBBReg(priv, rRx_IQK_Tone_A, bMaskDWord, 0x10008c1c);
|
|
PHY_SetBBReg(priv, rTx_IQK_PI_A, bMaskDWord, 0x82160c05);
|
|
PHY_SetBBReg(priv, rRx_IQK_PI_A, bMaskDWord, 0x28160c05);
|
|
|
|
//LO calibration setting
|
|
DEBUG_INFO("LO calibration setting!\n");
|
|
PHY_SetBBReg(priv, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911); //0x0010a8d1
|
|
|
|
//One shot, path A LOK & IQK
|
|
DEBUG_INFO("One shot, path A LOK & IQK!\n");
|
|
PHY_SetBBReg(priv, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
|
|
PHY_SetBBReg(priv, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
|
|
|
|
// delay x ms
|
|
DEBUG_INFO("Delay %d ms for One shot, path A LOK & IQK.\n", IQK_DELAY_TIME_88E);
|
|
delay_ms(IQK_DELAY_TIME_88E);
|
|
|
|
// Check failed
|
|
regEAC = PHY_QueryBBReg(priv, rRx_Power_After_IQK_A_2, bMaskDWord);
|
|
DEBUG_INFO("0xeac = 0x%x\n", regEAC);
|
|
regE94 = PHY_QueryBBReg(priv, rTx_Power_Before_IQK_A, bMaskDWord);
|
|
DEBUG_INFO("0xe94 = 0x%x\n", regE94);
|
|
regE9C= PHY_QueryBBReg(priv, rTx_Power_After_IQK_A, bMaskDWord);
|
|
DEBUG_INFO("0xe9c = 0x%x\n", regE9C);
|
|
regEA4= PHY_QueryBBReg(priv, rRx_Power_Before_IQK_A_2, bMaskDWord);
|
|
DEBUG_INFO("0xea4 = 0x%x\n", regEA4);
|
|
|
|
#if 0
|
|
if(!(regEAC & BIT28) &&
|
|
(((regE94 & 0x03FF0000)>>16) != 0x142) &&
|
|
(((regE9C & 0x03FF0000)>>16) != 0x42) )
|
|
result |= 0x01;
|
|
else //if Tx not OK, ignore Rx
|
|
return result;
|
|
#endif
|
|
|
|
if(!(regEAC & BIT(27)) && //if Tx is OK, check whether Rx is OK
|
|
(((regEA4 & 0x03FF0000)>>16) != 0x132) &&
|
|
(((regEAC & 0x03FF0000)>>16) != 0x36))
|
|
result |= 0x02;
|
|
else
|
|
DEBUG_INFO("Path A Rx IQK fail!!\n");
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
//bit0 = 1 => Tx OK, bit1 = 1 => Rx OK
|
|
unsigned char phy_PathB_IQK_8188E(struct rtl8192cd_priv *priv)
|
|
{
|
|
unsigned int regEAC, regEB4, regEBC, regEC4, regECC;
|
|
unsigned char result = 0x00;
|
|
DEBUG_INFO("Path B IQK!\n");
|
|
|
|
//One shot, path B LOK & IQK
|
|
DEBUG_INFO("One shot, path A LOK & IQK!\n");
|
|
PHY_SetBBReg(priv, rIQK_AGC_Cont, bMaskDWord, 0x00000002);
|
|
PHY_SetBBReg(priv, rIQK_AGC_Cont, bMaskDWord, 0x00000000);
|
|
|
|
// delay x ms
|
|
DEBUG_INFO("Delay %d ms for One shot, path B LOK & IQK.\n", IQK_DELAY_TIME_88E);
|
|
delay_ms(IQK_DELAY_TIME_88E);
|
|
|
|
// Check failed
|
|
regEAC = PHY_QueryBBReg(priv, rRx_Power_After_IQK_A_2, bMaskDWord);
|
|
DEBUG_INFO("0xeac = 0x%x\n", regEAC);
|
|
regEB4 = PHY_QueryBBReg(priv, rTx_Power_Before_IQK_B, bMaskDWord);
|
|
DEBUG_INFO("0xeb4 = 0x%x\n", regEB4);
|
|
regEBC= PHY_QueryBBReg(priv, rTx_Power_After_IQK_B, bMaskDWord);
|
|
DEBUG_INFO("0xebc = 0x%x\n", regEBC);
|
|
regEC4= PHY_QueryBBReg(priv, rRx_Power_Before_IQK_B_2, bMaskDWord);
|
|
DEBUG_INFO("0xec4 = 0x%x\n", regEC4);
|
|
regECC= PHY_QueryBBReg(priv, rRx_Power_After_IQK_B_2, bMaskDWord);
|
|
DEBUG_INFO("0xecc = 0x%x\n", regECC);
|
|
|
|
if(!(regEAC & BIT(31)) &&
|
|
(((regEB4 & 0x03FF0000)>>16) != 0x142) &&
|
|
(((regEBC & 0x03FF0000)>>16) != 0x42))
|
|
result |= 0x01;
|
|
else
|
|
return result;
|
|
|
|
if(!(regEAC & BIT(30)) &&
|
|
(((regEC4 & 0x03FF0000)>>16) != 0x132) &&
|
|
(((regECC & 0x03FF0000)>>16) != 0x36))
|
|
result |= 0x02;
|
|
else
|
|
DEBUG_INFO("Path B Rx IQK fail!!\n");
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
void phy_IQCalibrate_8188E(struct rtl8192cd_priv *priv, int result[][8], unsigned char t, char is2T)
|
|
{
|
|
unsigned int i;
|
|
unsigned char PathAOK, PathBOK;
|
|
unsigned int 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 };
|
|
|
|
unsigned int 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
|
|
unsigned int 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, /*rFPGA0_RFMOD*/ rCCK0_AFESetting
|
|
};
|
|
|
|
unsigned int retryCount = 0;
|
|
|
|
// unsigned int bbvalue;
|
|
|
|
#ifdef MP_TEST
|
|
if(priv->pshare->rf_ft_var.mp_specific)
|
|
retryCount = 9; //original 9
|
|
else
|
|
retryCount = 2;
|
|
#else
|
|
retryCount = 2;
|
|
#endif
|
|
|
|
// Note: IQ calibration must be performed after loading
|
|
// PHY_REG.txt , and radio_a, radio_b.txt
|
|
|
|
if(t == 0)
|
|
{
|
|
// bbvalue = PHY_QueryBBReg(pAdapter, rFPGA0_RFMOD, bMaskDWord);
|
|
// RTPRINT(FINIT, INIT_IQK, ("phy_IQCalibrate_8188E()==>0x%08x\n",bbvalue));
|
|
|
|
//RTPRINT(FINIT, INIT_IQK, ("IQ Calibration for %s for %d times\n", (is2T ? "2T2R" : "1T1R"), t));
|
|
DEBUG_INFO("IQ Calibration for %s for %d times\n", (is2T ? "2T2R" : "1T1R"), t);
|
|
|
|
// Save ADDA parameters, turn Path A ADDA on
|
|
_PHY_SaveADDARegisters(priv, ADDA_REG, priv->pshare->ADDA_backup, IQK_ADDA_REG_NUM);
|
|
_PHY_SaveMACRegisters(priv, IQK_MAC_REG, priv->pshare->IQK_MAC_backup);
|
|
_PHY_SaveADDARegisters(priv, IQK_BB_REG_92C, priv->pshare->IQK_BB_backup, IQK_BB_REG_NUM);
|
|
|
|
}
|
|
DEBUG_INFO("IQ Calibration for %s for %d times\n", (is2T ? "2T2R" : "1T1R"), t);
|
|
|
|
|
|
_PHY_PathADDAOn(priv, ADDA_REG, TRUE, is2T);
|
|
|
|
|
|
if(t==0)
|
|
{
|
|
priv->pshare->bRfPiEnable = (unsigned char)PHY_QueryBBReg(priv, rFPGA0_XA_HSSIParameter1, BIT(8));
|
|
}
|
|
|
|
if(!priv->pshare->bRfPiEnable){
|
|
// Switch BB to PI mode to do IQ Calibration.
|
|
_PHY_PIModeSwitch(priv, TRUE);
|
|
}
|
|
|
|
//MAC settings
|
|
_PHY_MACSettingCalibration(priv, IQK_MAC_REG, priv->pshare->IQK_MAC_backup);
|
|
|
|
//BB setting
|
|
//PHY_SetBBReg(priv, rFPGA0_RFMOD, BIT(24), 0x00);
|
|
PHY_SetBBReg(priv, rCCK0_AFESetting, bMaskDWord, (0x0f000000 | (PHY_QueryBBReg(priv, rCCK0_AFESetting, bMaskDWord))) );
|
|
PHY_SetBBReg(priv, rOFDM0_TRxPathEnable, bMaskDWord, 0x03a05600);
|
|
PHY_SetBBReg(priv, rOFDM0_TRMuxPar, bMaskDWord, 0x000800e4);
|
|
PHY_SetBBReg(priv, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22204000);
|
|
|
|
PHY_SetBBReg(priv, rFPGA0_XAB_RFInterfaceSW, BIT(10), 0x01);
|
|
PHY_SetBBReg(priv, rFPGA0_XAB_RFInterfaceSW, BIT(26), 0x01);
|
|
PHY_SetBBReg(priv, rFPGA0_XA_RFInterfaceOE, BIT(10), 0x00);
|
|
PHY_SetBBReg(priv, rFPGA0_XB_RFInterfaceOE, BIT(10), 0x00);
|
|
|
|
|
|
if(is2T)
|
|
{
|
|
PHY_SetBBReg(priv, rFPGA0_XA_LSSIParameter, bMaskDWord, 0x00010000);
|
|
PHY_SetBBReg(priv, rFPGA0_XB_LSSIParameter, bMaskDWord, 0x00010000);
|
|
}
|
|
|
|
//Page B init
|
|
//AP or IQK
|
|
PHY_SetBBReg(priv, rConfig_AntA, bMaskDWord, 0x0f600000);
|
|
|
|
if(is2T)
|
|
{
|
|
PHY_SetBBReg(priv, rConfig_AntB, bMaskDWord, 0x0f600000);
|
|
}
|
|
|
|
// IQ calibration setting
|
|
DEBUG_INFO("IQK setting!\n");
|
|
PHY_SetBBReg(priv, rFPGA0_IQK, 0xffffff00, 0x808000);
|
|
PHY_SetBBReg(priv, rTx_IQK, bMaskDWord, 0x01007c00);
|
|
PHY_SetBBReg(priv, rRx_IQK, bMaskDWord, 0x81004800);
|
|
|
|
for(i = 0 ; i < retryCount ; i++){
|
|
PathAOK = phy_PathA_IQK_8188E(priv, is2T);
|
|
// if(PathAOK == 0x03){
|
|
if(PathAOK == 0x01){
|
|
DEBUG_INFO("Path A Tx IQK Success!!\n");
|
|
result[t][0] = (PHY_QueryBBReg(priv, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16;
|
|
result[t][1] = (PHY_QueryBBReg(priv, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16;
|
|
break;
|
|
}
|
|
#if 0
|
|
else if (i == (retryCount-1) && PathAOK == 0x01) //Tx IQK OK
|
|
{
|
|
DEBUG_INFO("Path A IQK Only Tx Success!!\n");
|
|
|
|
result[t][0] = (PHY_QueryBBReg(priv, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16;
|
|
result[t][1] = (PHY_QueryBBReg(priv, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
for(i = 0 ; i < retryCount ; i++){
|
|
PathAOK = phy_PathA_RxIQK(priv, is2T);
|
|
|
|
//printk("\n\nPathAOK = 0x%x\n\n", PathAOK);
|
|
|
|
if(PathAOK == 0x03){
|
|
DEBUG_INFO("Path A Rx IQK Success!!\n");
|
|
// result[t][0] = (PHY_QueryBBReg(pAdapter, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16;
|
|
// result[t][1] = (PHY_QueryBBReg(pAdapter, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16;
|
|
result[t][2] = (PHY_QueryBBReg(priv, rRx_Power_Before_IQK_A_2, bMaskDWord)&0x3FF0000)>>16;
|
|
result[t][3] = (PHY_QueryBBReg(priv, rRx_Power_After_IQK_A_2, bMaskDWord)&0x3FF0000)>>16;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
DEBUG_INFO("Path A Rx IQK Fail!!\n");
|
|
}
|
|
}
|
|
|
|
if(0x00 == PathAOK){
|
|
DEBUG_INFO("Path A IQK failed!!\n");
|
|
}
|
|
|
|
if(is2T){
|
|
_PHY_PathAStandBy(priv);
|
|
|
|
// Turn Path B ADDA on
|
|
_PHY_PathADDAOn(priv, ADDA_REG, FALSE, is2T);
|
|
|
|
for(i = 0 ; i < retryCount ; i++){
|
|
PathBOK = phy_PathB_IQK_8188E(priv);
|
|
if(PathBOK == 0x03){
|
|
DEBUG_INFO("Path B IQK Success!!\n");
|
|
result[t][4] = (PHY_QueryBBReg(priv, rTx_Power_Before_IQK_B, bMaskDWord)&0x3FF0000)>>16;
|
|
result[t][5] = (PHY_QueryBBReg(priv, rTx_Power_After_IQK_B, bMaskDWord)&0x3FF0000)>>16;
|
|
result[t][6] = (PHY_QueryBBReg(priv, rRx_Power_Before_IQK_B_2, bMaskDWord)&0x3FF0000)>>16;
|
|
result[t][7] = (PHY_QueryBBReg(priv, rRx_Power_After_IQK_B_2, bMaskDWord)&0x3FF0000)>>16;
|
|
break;
|
|
}
|
|
else if (i == (retryCount - 1) && PathBOK == 0x01) //Tx IQK OK
|
|
{
|
|
DEBUG_INFO("Path B Only Tx IQK Success!!\n");
|
|
result[t][4] = (PHY_QueryBBReg(priv, rTx_Power_Before_IQK_B, bMaskDWord)&0x3FF0000)>>16;
|
|
result[t][5] = (PHY_QueryBBReg(priv, rTx_Power_After_IQK_B, bMaskDWord)&0x3FF0000)>>16;
|
|
}
|
|
}
|
|
|
|
if(0x00 == PathBOK){
|
|
DEBUG_INFO("Path B IQK failed!!\n");
|
|
}
|
|
}
|
|
|
|
//Back to BB mode, load original value
|
|
DEBUG_INFO("IQK:Back to BB mode, load original value!\n");
|
|
PHY_SetBBReg(priv, rFPGA0_IQK, 0xffffff00, 0);
|
|
|
|
if(t != 0)
|
|
{
|
|
if(!priv->pshare->bRfPiEnable){
|
|
// Switch back BB to SI mode after finish IQ Calibration.
|
|
_PHY_PIModeSwitch(priv, FALSE);
|
|
}
|
|
|
|
// Reload ADDA power saving parameters
|
|
_PHY_ReloadADDARegisters(priv, ADDA_REG, priv->pshare->ADDA_backup, IQK_ADDA_REG_NUM);
|
|
|
|
// Reload MAC parameters
|
|
_PHY_ReloadMACRegisters(priv, IQK_MAC_REG, priv->pshare->IQK_MAC_backup);
|
|
|
|
_PHY_ReloadADDARegisters(priv, IQK_BB_REG_92C, priv->pshare->IQK_BB_backup, IQK_BB_REG_NUM);
|
|
|
|
// Restore RX initial gain
|
|
PHY_SetBBReg(priv, rFPGA0_XA_LSSIParameter, bMaskDWord, 0x00032ed3);
|
|
if(is2T){
|
|
PHY_SetBBReg(priv, rFPGA0_XB_LSSIParameter, bMaskDWord, 0x00032ed3);
|
|
}
|
|
|
|
//load 0xe30 IQC default value
|
|
PHY_SetBBReg(priv, rTx_IQK_Tone_A, bMaskDWord, 0x01008c00);
|
|
PHY_SetBBReg(priv, rRx_IQK_Tone_A, bMaskDWord, 0x01008c00);
|
|
|
|
}
|
|
DEBUG_INFO("phy_IQCalibrate_8188E() <==\n");
|
|
|
|
}
|
|
|
|
|
|
unsigned char phy_SimularityCompare_8188E(struct rtl8192cd_priv *priv, int result[][8], unsigned char c1, unsigned char c2)
|
|
{
|
|
unsigned int i, j, diff, SimularityBitMap, bound = 0;
|
|
unsigned char final_candidate[2] = {0xFF, 0xFF}; //for path A and path B
|
|
unsigned char bResult = TRUE, is2T = FALSE;
|
|
|
|
if(is2T)
|
|
bound = 8;
|
|
else
|
|
bound = 4;
|
|
|
|
DEBUG_INFO("===> IQK:phy_SimularityCompare_8188E c1 %d c2 %d!!!\n", c1, c2);
|
|
|
|
|
|
SimularityBitMap = 0;
|
|
|
|
for( i = 0; i < bound; i++ )
|
|
{
|
|
diff = (result[c1][i] > result[c2][i]) ? (result[c1][i] - result[c2][i]) : (result[c2][i] - result[c1][i]);
|
|
if (diff > MAX_TOLERANCE)
|
|
{
|
|
DEBUG_INFO("IQK:phy_SimularityCompare_8188E differnece overflow index %d compare1 0x%x compare2 0x%x!!!\n", i, result[c1][i], result[c2][i]);
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
DEBUG_INFO("IQK:phy_SimularityCompare_8188E SimularityBitMap %d !!!\n", SimularityBitMap);
|
|
|
|
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 & 0x0F)) //path A OK
|
|
{
|
|
for(i = 0; i < 4; i++)
|
|
result[3][i] = result[c1][i];
|
|
return FALSE;
|
|
}
|
|
else if (!(SimularityBitMap & 0xF0) && is2T) //path B OK
|
|
{
|
|
for(i = 4; i < 8; i++)
|
|
result[3][i] = result[c1][i];
|
|
return FALSE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PHY_IQCalibrate_8188E(struct rtl8192cd_priv *priv, char bReCovery)
|
|
{
|
|
int result[4][8]; //last is final result
|
|
unsigned char i, final_candidate, Indexforchannel;
|
|
char bPathAOK, bPathBOK;
|
|
int RegE94, RegE9C, RegEA4, RegEAC, RegEB4, RegEBC, RegEC4, RegECC, RegTmp = 0;
|
|
char is12simular, is13simular, is23simular;
|
|
// char bStartContTx = FALSE, bSingleTone = FALSE;
|
|
int 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};
|
|
|
|
//default disable
|
|
// return;
|
|
|
|
|
|
#ifdef MP_TEST
|
|
if(priv->pshare->rf_ft_var.mp_specific)
|
|
{
|
|
if((OPMODE & WIFI_MP_CTX_PACKET) || (OPMODE & WIFI_MP_CTX_ST))
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
#if 1
|
|
if(priv->pshare->IQK_88E_done)
|
|
{
|
|
#ifdef __ECOS
|
|
_PHY_ReloadADDARegisters(priv, (unsigned int*)IQK_BB_REG_92C, priv->pshare->IQK_BB_backup_recover, 9);
|
|
#else
|
|
_PHY_ReloadADDARegisters(priv, IQK_BB_REG_92C, priv->pshare->IQK_BB_backup_recover, 9);
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
priv->pshare->IQK_88E_done = 1;
|
|
#endif
|
|
|
|
#if 0
|
|
if(bReCovery)
|
|
{
|
|
_PHY_ReloadADDARegisters(priv, IQK_BB_REG_92C, priv->pshare->IQK_BB_backup_recover, 9);
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
printk("DO 8188E IQK !!!\n");
|
|
DEBUG_INFO("IQK:Start!!!\n");
|
|
|
|
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;
|
|
|
|
|
|
//RTPRINT(("IQK !!!interface %d currentband %d ishardwareD %d \n", pAdapter->interfaceIndex, pHalData->CurrentBandType92D, IS_HARDWARE_TYPE_8192D(pAdapter)));
|
|
//RT_TRACE(COMP_INIT,DBG_LOUD,("Acquire Mutex in IQCalibrate \n"));
|
|
|
|
for (i=0; i<3; i++)
|
|
{
|
|
|
|
// For 88C 1T1R //_eric ??
|
|
phy_IQCalibrate_8188E(priv, result, i, FALSE);
|
|
|
|
if(i == 1)
|
|
{
|
|
is12simular = phy_SimularityCompare_8188E(priv, result, 0, 1);
|
|
if(is12simular)
|
|
{
|
|
final_candidate = 0;
|
|
DEBUG_INFO("IQK: is12simular final_candidate is %x\n",final_candidate);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(i == 2)
|
|
{
|
|
is13simular = phy_SimularityCompare_8188E(priv, result, 0, 2);
|
|
if(is13simular)
|
|
{
|
|
final_candidate = 0;
|
|
DEBUG_INFO("IQK: is13simular final_candidate is %x\n",final_candidate);
|
|
|
|
break;
|
|
}
|
|
|
|
is23simular = phy_SimularityCompare_8188E(priv, result, 1, 2);
|
|
if(is23simular)
|
|
{
|
|
final_candidate = 1;
|
|
DEBUG_INFO("IQK: is23simular final_candidate is %x\n",final_candidate);
|
|
}
|
|
else
|
|
{
|
|
for(i = 0; i < 8; i++)
|
|
RegTmp += result[3][i];
|
|
|
|
if(RegTmp != 0)
|
|
final_candidate = 3;
|
|
else
|
|
final_candidate = 0xFF;
|
|
}
|
|
}
|
|
}
|
|
// RT_TRACE(COMP_INIT,DBG_LOUD,("Release Mutex in IQCalibrate \n"));
|
|
|
|
for (i=0; i<4; i++)
|
|
{
|
|
RegE94 = result[i][0];
|
|
RegE9C = result[i][1];
|
|
RegEA4 = result[i][2];
|
|
RegEAC = result[i][3];
|
|
RegEB4 = result[i][4];
|
|
RegEBC = result[i][5];
|
|
RegEC4 = result[i][6];
|
|
RegECC = result[i][7];
|
|
DEBUG_INFO("IQK: RegE94=%x RegE9C=%x RegEA4=%x RegEAC=%x RegEB4=%x RegEBC=%x RegEC4=%x RegECC=%x\n ", RegE94, RegE9C, RegEA4, RegEAC, RegEB4, RegEBC, RegEC4, RegECC);
|
|
}
|
|
|
|
if(final_candidate != 0xff)
|
|
{
|
|
priv->pshare->RegE94 = RegE94 = result[final_candidate][0];
|
|
priv->pshare->RegE9C = RegE9C = result[final_candidate][1];
|
|
RegEA4 = result[final_candidate][2];
|
|
RegEAC = result[final_candidate][3];
|
|
priv->pshare->RegEB4 = RegEB4 = result[final_candidate][4];
|
|
priv->pshare->RegEBC = RegEBC = result[final_candidate][5];
|
|
RegEC4 = result[final_candidate][6];
|
|
RegECC = result[final_candidate][7];
|
|
DEBUG_INFO("IQK: final_candidate is %x\n",final_candidate);
|
|
DEBUG_INFO("IQK: RegE94=%x RegE9C=%x RegEA4=%x RegEAC=%x RegEB4=%x RegEBC=%x RegEC4=%x RegECC=%x\n ", RegE94, RegE9C, RegEA4, RegEAC, RegEB4, RegEBC, RegEC4, RegECC);
|
|
bPathAOK = bPathBOK = TRUE;
|
|
}
|
|
else
|
|
{
|
|
DEBUG_INFO("IQK: FAIL use default value\n");
|
|
|
|
priv->pshare->RegE94 = priv->pshare->RegEB4 = 0x100; //X default value
|
|
priv->pshare->RegE9C = priv->pshare->RegEBC = 0x0; //Y default value
|
|
}
|
|
|
|
|
|
|
|
if((RegE94 != 0)/*&&(RegEA4 != 0)*/)
|
|
{
|
|
_PHY_PathAFillIQKMatrix(priv, bPathAOK, result, final_candidate, (RegEA4 == 0));
|
|
}
|
|
|
|
#if 0
|
|
if (IS_92C_SERIAL(pHalData->VersionID))
|
|
{
|
|
if((RegEB4 != 0)/*&&(RegEC4 != 0)*/)
|
|
{
|
|
_PHY_PathBFillIQKMatrix(pAdapter, bPathBOK, result, final_candidate, (RegEC4 == 0));
|
|
}
|
|
}
|
|
#endif
|
|
Indexforchannel = 0;
|
|
|
|
for(i = 0; i < IQK_Matrix_REG_NUM; i++)
|
|
priv->pshare->IQKMatrixRegSetting[Indexforchannel].Value[0][i] = result[final_candidate][i];
|
|
|
|
priv->pshare->IQKMatrixRegSetting[Indexforchannel].bIQKDone = TRUE;
|
|
#ifdef __ECOS
|
|
_PHY_SaveADDARegisters(priv, (unsigned int*)IQK_BB_REG_92C, priv->pshare->IQK_BB_backup_recover, 9);
|
|
#else
|
|
_PHY_SaveADDARegisters(priv, IQK_BB_REG_92C, priv->pshare->IQK_BB_backup_recover, 9);
|
|
#endif
|
|
|
|
}
|
|
|
|
void ODM_ResetIQKResult(struct rtl8192cd_priv *priv)
|
|
{
|
|
/*
|
|
#if (DM_ODM_SUPPORT_TYPE == ODM_WIN || DM_ODM_SUPPORT_TYPE == ODM_CE)
|
|
PADAPTER Adapter = pDM_Odm->Adapter;
|
|
u1Byte i;
|
|
|
|
if (!IS_HARDWARE_TYPE_8192D(Adapter))
|
|
return;
|
|
#endif
|
|
*/
|
|
|
|
unsigned char i;
|
|
|
|
//printk("PHY_ResetIQKResult:: settings regs %d default regs %d\n", sizeof(priv->pshare->IQKMatrixRegSetting)/sizeof(IQK_MATRIX_REGS_SETTING), IQK_Matrix_Settings_NUM);
|
|
//0xe94, 0xe9c, 0xea4, 0xeac, 0xeb4, 0xebc, 0xec4, 0xecc
|
|
|
|
for(i = 0; i < IQK_Matrix_Settings_NUM; i++)
|
|
{
|
|
{
|
|
priv->pshare->IQKMatrixRegSetting[i].Value[0][0] =
|
|
priv->pshare->IQKMatrixRegSetting[i].Value[0][2] =
|
|
priv->pshare->IQKMatrixRegSetting[i].Value[0][4] =
|
|
priv->pshare->IQKMatrixRegSetting[i].Value[0][6] = 0x100;
|
|
|
|
priv->pshare->IQKMatrixRegSetting[i].Value[0][1] =
|
|
priv->pshare->IQKMatrixRegSetting[i].Value[0][3] =
|
|
priv->pshare->IQKMatrixRegSetting[i].Value[0][5] =
|
|
priv->pshare->IQKMatrixRegSetting[i].Value[0][7] = 0x0;
|
|
|
|
priv->pshare->IQKMatrixRegSetting[i].bIQKDone = FALSE;
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
#define OFDM_TABLE_SIZE_92D 43
|
|
|
|
#define bRFRegOffsetMask 0xfffff
|
|
|
|
extern unsigned int OFDMSwingTable[];
|
|
extern const int OFDM_TABLE_SIZE;
|
|
extern const int CCK_TABLE_SIZE;
|
|
extern unsigned char CCKSwingTable_Ch14 [][8];
|
|
extern unsigned char CCKSwingTable_Ch1_Ch13[][8];
|
|
|
|
|
|
//091212 chiyokolin
|
|
void odm_TXPowerTrackingCallback_ThermalMeter_8188E(struct rtl8192cd_priv *priv)
|
|
{
|
|
|
|
//HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
|
|
|
|
unsigned char ThermalValue = 0, delta, delta_LCK, delta_IQK, offset;
|
|
unsigned char ThermalValue_AVG_count = 0;
|
|
unsigned int ThermalValue_AVG = 0;
|
|
int ele_A=0, ele_D, /* TempCCk,*/ X, value32;
|
|
int Y, ele_C=0;
|
|
s1Byte OFDM_index[2]={0}, CCK_index=0, OFDM_index_old[2]={0}, CCK_index_old=0, index;
|
|
unsigned int i = 0, j = 0;
|
|
char is2T = FALSE;
|
|
// char bInteralPA = FALSE;
|
|
|
|
unsigned char OFDM_min_index = 6, rf; //OFDM BB Swing should be less than +3.0dB, which is required by Arthur
|
|
unsigned char Indexforchannel = 0/*GetRightChnlPlaceforIQK(pHalData->CurrentChannel)*/;
|
|
s1Byte OFDM_index_mapping[2][index_mapping_NUM_88E] = {
|
|
{0, 0, 2, 3, 4, 4, //2.4G, decrease power
|
|
5, 6, 7, 7, 8, 9,
|
|
10, 10, 11}, // For lower temperature, 20120220 updated on 20120220.
|
|
{0, 0, -1, -2, -3, -4, //2.4G, increase power
|
|
-4, -4, -4, -5, -7, -8,
|
|
-9, -9, -10},
|
|
};
|
|
unsigned char Thermal_mapping[2][index_mapping_NUM_88E] = {
|
|
{0, 2, 4, 6, 8, 10, //2.4G, decrease power
|
|
12, 14, 16, 18, 20, 22,
|
|
24, 26, 27},
|
|
{0, 2, 4, 6, 8, 10, //2.4G,, increase power
|
|
12, 14, 16, 18, 20, 22,
|
|
25, 25, 25},
|
|
};
|
|
|
|
priv->pshare->TXPowerTrackingCallbackCnt++; //cosa add for debug
|
|
priv->pshare->bTXPowerTrackingInit = TRUE;
|
|
|
|
#if 1 //(MP_DRIVER == 1) //_eric_??
|
|
priv->pshare->TxPowerTrackControl = 1; //priv->pshare->TxPowerTrackControl; //_eric_?? // <Kordan> We should keep updating the control variable according to HalData.
|
|
// <Kordan> pshare->RegA24 will be initialized when ODM HW configuring, but MP configures with para files.
|
|
priv->pshare->RegA24 = 0x090e1317;
|
|
#endif
|
|
|
|
|
|
#ifdef MP_TEST
|
|
if ((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific) {
|
|
if(priv->pshare->mp_txpwr_tracking == FALSE)
|
|
return;
|
|
}
|
|
#endif
|
|
#if 0
|
|
if(priv->pshare->Power_tracking_on_88E == 0)
|
|
{
|
|
priv->pshare->Power_tracking_on_88E = 1;
|
|
PHY_SetRFReg(priv, RF92CD_PATH_A, 0x42, (BIT(17) | BIT(16)), 0x03);
|
|
return;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
|
|
// priv->pshare->Power_tracking_on_88E = 0;
|
|
|
|
//printk("===>dm_TXPowerTrackingCallback_ThermalMeter_8188E txpowercontrol %d\n", priv->pshare->TxPowerTrackControl);
|
|
|
|
ThermalValue = (unsigned char)PHY_QueryRFReg(priv, RF_PATH_A, RF_T_METER_88E, 0xfc00, 1); //0x42: RF Reg[15:10] 88E
|
|
|
|
//printk("\nReadback Thermal Meter = 0x%x pre thermal meter 0x%x EEPROMthermalmeter 0x%x\n", ThermalValue, priv->pshare->ThermalValue, priv->pmib->dot11RFEntry.ther);
|
|
|
|
}
|
|
|
|
|
|
if(is2T)
|
|
rf = 2;
|
|
else
|
|
rf = 1;
|
|
|
|
//if(ThermalValue)
|
|
{
|
|
// if(!pHalData->ThermalValue)
|
|
{
|
|
//Query OFDM path A default setting
|
|
ele_D = PHY_QueryBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord)&bMaskOFDM_D;
|
|
|
|
for(i=0; i<OFDM_TABLE_SIZE_92D; i++) //find the index
|
|
{
|
|
if(ele_D == (OFDMSwingTable[i]&bMaskOFDM_D))
|
|
{
|
|
OFDM_index_old[0] = (unsigned char)i;
|
|
printk("Initial pathA ele_D reg0x%x = 0x%x, OFDM_index=0x%x\n",
|
|
rOFDM0_XATxIQImbalance, ele_D, OFDM_index_old[0]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
//Query OFDM path B default setting
|
|
if(is2T)
|
|
{
|
|
ele_D = PHY_QueryBBReg(priv, rOFDM0_XBTxIQImbalance, bMaskDWord)&bMaskOFDM_D;
|
|
for(i=0; i<OFDM_TABLE_SIZE_92D; i++) //find the index
|
|
{
|
|
if(ele_D == (OFDMSwingTable[i]&bMaskOFDM_D))
|
|
{
|
|
OFDM_index_old[1] = (unsigned char)i;
|
|
printk("Initial pathB ele_D reg0x%x = 0x%x, OFDM_index=0x%x\n",
|
|
rOFDM0_XBTxIQImbalance, ele_D, OFDM_index_old[1]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
//Query CCK default setting From 0xa24
|
|
#if 0
|
|
TempCCk = priv->pshare->RegA24;
|
|
|
|
for(i=0 ; i<CCK_TABLE_SIZE ; i++)
|
|
{
|
|
if(priv->pshare->bCCKinCH14)
|
|
{
|
|
if(memcmp((void*)&TempCCk, (void*)&CCKSwingTable_Ch14[i][2], 4)==0)
|
|
{
|
|
CCK_index_old =(unsigned char) i;
|
|
//printk("Initial reg0x%x = 0x%x, CCK_index=0x%x, ch 14 %d\n",
|
|
//rCCK0_TxFilter2, TempCCk, CCK_index_old, priv->pshare->bCCKinCH14);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//printk("RegA24: 0x%X, CCKSwingTable_Ch1_Ch13[%d][2]: CCKSwingTable_Ch1_Ch13[i][2]: 0x%X\n", TempCCk, i, CCKSwingTable_Ch1_Ch13[i][2]);
|
|
if(memcmp((void*)&TempCCk, (void*)&CCKSwingTable_Ch1_Ch13[i][2], 4)==0)
|
|
{
|
|
CCK_index_old =(unsigned char) i;
|
|
//printk("Initial reg0x%x = 0x%x, CCK_index=0x%x, ch14 %d\n",
|
|
//rCCK0_TxFilter2, TempCCk, CCK_index_old, priv->pshare->bCCKinCH14);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if(!priv->pshare->ThermalValue)
|
|
{
|
|
CCK_index_old = get_CCK_swing_index(priv);
|
|
priv->pshare->ThermalValue = priv->pmib->dot11RFEntry.ther;
|
|
priv->pshare->ThermalValue_LCK = ThermalValue;
|
|
priv->pshare->ThermalValue_IQK = ThermalValue;
|
|
|
|
for(i = 0; i < rf; i++)
|
|
priv->pshare->OFDM_index[i] = OFDM_index_old[i];
|
|
priv->pshare->CCK_index = CCK_index_old;
|
|
}
|
|
|
|
if(priv->pshare->bReloadtxpowerindex)
|
|
{
|
|
printk("reload ofdm index for band switch\n");
|
|
}
|
|
|
|
//calculate average thermal meter
|
|
{
|
|
priv->pshare->ThermalValue_AVG[priv->pshare->ThermalValue_AVG_index] = ThermalValue;
|
|
priv->pshare->ThermalValue_AVG_index++;
|
|
if(priv->pshare->ThermalValue_AVG_index == AVG_THERMAL_NUM_88E)
|
|
priv->pshare->ThermalValue_AVG_index = 0;
|
|
|
|
for(i = 0; i < AVG_THERMAL_NUM_88E; i++)
|
|
{
|
|
if(priv->pshare->ThermalValue_AVG[i])
|
|
{
|
|
ThermalValue_AVG += priv->pshare->ThermalValue_AVG[i];
|
|
ThermalValue_AVG_count++;
|
|
}
|
|
}
|
|
|
|
if(ThermalValue_AVG_count)
|
|
{
|
|
ThermalValue = (unsigned char)(ThermalValue_AVG / ThermalValue_AVG_count);
|
|
//printk("AVG Thermal Meter = 0x%x \n", ThermalValue);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(priv->pshare->bReloadtxpowerindex)
|
|
{
|
|
delta = ThermalValue > priv->pmib->dot11RFEntry.ther?(ThermalValue - priv->pmib->dot11RFEntry.ther):(priv->pmib->dot11RFEntry.ther - ThermalValue);
|
|
priv->pshare->bReloadtxpowerindex = FALSE;
|
|
priv->pshare->bDoneTxpower = FALSE;
|
|
}
|
|
else if(priv->pshare->bDoneTxpower)
|
|
{
|
|
delta = (ThermalValue > priv->pshare->ThermalValue)?(ThermalValue - priv->pshare->ThermalValue):(priv->pshare->ThermalValue - ThermalValue);
|
|
}
|
|
else
|
|
{
|
|
delta = ThermalValue > priv->pmib->dot11RFEntry.ther?(ThermalValue - priv->pmib->dot11RFEntry.ther):(priv->pmib->dot11RFEntry.ther - ThermalValue);
|
|
}
|
|
delta_LCK = (ThermalValue > priv->pshare->ThermalValue_LCK)?(ThermalValue - priv->pshare->ThermalValue_LCK):(priv->pshare->ThermalValue_LCK - ThermalValue);
|
|
delta_IQK = (ThermalValue > priv->pshare->ThermalValue_IQK)?(ThermalValue - priv->pshare->ThermalValue_IQK):(priv->pshare->ThermalValue_IQK - ThermalValue);
|
|
|
|
//printk("Readback Thermal Meter = 0x%x \npre thermal meter 0x%x EEPROMthermalmeter 0x%x delta 0x%x \ndelta_LCK 0x%x delta_IQK 0x%x \n", ThermalValue, priv->pshare->ThermalValue, priv->pshare->EEPROMThermalMeter, delta, delta_LCK, delta_IQK);
|
|
//printk("pre thermal meter LCK 0x%x \npre thermal meter IQK 0x%x \ndelta_LCK_bound 0x%x delta_IQK_bound 0x%x\n", priv->pshare->ThermalValue_LCK, priv->pshare->ThermalValue_IQK, priv->pshare->Delta_LCK, priv->pshare->Delta_IQK);
|
|
|
|
|
|
//if((delta_LCK > pHalData->Delta_LCK) && (pHalData->Delta_LCK != 0))
|
|
if (delta_LCK >= 8) // Delta temperature is equal to or larger than 20 centigrade.
|
|
{
|
|
priv->pshare->ThermalValue_LCK = ThermalValue;
|
|
PHY_LCCalibrate(priv);
|
|
}
|
|
|
|
|
|
if(delta > 0 && priv->pshare->TxPowerTrackControl)
|
|
{
|
|
delta = ThermalValue > priv->pmib->dot11RFEntry.ther?(ThermalValue - priv->pmib->dot11RFEntry.ther):(priv->pmib->dot11RFEntry.ther - ThermalValue);
|
|
|
|
//calculate new OFDM / CCK offset
|
|
{
|
|
{
|
|
if(ThermalValue > priv->pmib->dot11RFEntry.ther)
|
|
j = 1;
|
|
else
|
|
j = 0;
|
|
|
|
for(offset = 0; offset < index_mapping_NUM_88E; offset++)
|
|
{
|
|
if(delta < Thermal_mapping[j][offset])
|
|
{
|
|
if(offset != 0)
|
|
offset--;
|
|
break;
|
|
}
|
|
}
|
|
if(offset >= index_mapping_NUM_88E)
|
|
offset = index_mapping_NUM_88E-1;
|
|
|
|
index = OFDM_index_mapping[j][offset];
|
|
|
|
printk("\nj = %d delta = %d, index = %d\n\n", j, delta, index);
|
|
|
|
for(i = 0; i < rf; i++)
|
|
OFDM_index[i] = priv->pshare->OFDM_index[i] + OFDM_index_mapping[j][offset];
|
|
CCK_index = priv->pshare->CCK_index + OFDM_index_mapping[j][offset];
|
|
}
|
|
|
|
if(is2T)
|
|
{
|
|
printk("temp OFDM_A_index=0x%x, OFDM_B_index=0x%x, CCK_index=0x%x\n",
|
|
priv->pshare->OFDM_index[0], priv->pshare->OFDM_index[1], priv->pshare->CCK_index);
|
|
}
|
|
else
|
|
{
|
|
printk("temp OFDM_A_index=0x%x, CCK_index=0x%x\n",
|
|
priv->pshare->OFDM_index[0], priv->pshare->CCK_index);
|
|
}
|
|
|
|
for(i = 0; i < rf; i++)
|
|
{
|
|
if(OFDM_index[i] > OFDM_TABLE_SIZE_92D-1)
|
|
{
|
|
OFDM_index[i] = OFDM_TABLE_SIZE_92D-1;
|
|
}
|
|
else if (OFDM_index[i] < OFDM_min_index)
|
|
{
|
|
OFDM_index[i] = OFDM_min_index;
|
|
}
|
|
}
|
|
|
|
{
|
|
if(CCK_index > CCK_TABLE_SIZE-1)
|
|
CCK_index = CCK_TABLE_SIZE-1;
|
|
else if (CCK_index < 0)
|
|
CCK_index = 0;
|
|
}
|
|
|
|
if(is2T)
|
|
{
|
|
printk("new OFDM_A_index=0x%x, OFDM_B_index=0x%x, CCK_index=0x%x\n",
|
|
OFDM_index[0], OFDM_index[1], CCK_index);
|
|
}
|
|
else
|
|
{
|
|
printk("new OFDM_A_index=0x%x, CCK_index=0x%x\n",
|
|
OFDM_index[0], CCK_index);
|
|
}
|
|
}
|
|
|
|
//2 temporarily remove bNOPG
|
|
//Config by SwingTable
|
|
if(priv->pshare->TxPowerTrackControl /*&& !pHalData->bNOPG*/)
|
|
{
|
|
priv->pshare->bDoneTxpower = TRUE;
|
|
|
|
//Adujst OFDM Ant_A according to IQK result
|
|
ele_D = (OFDMSwingTable[(unsigned char)OFDM_index[0]] & 0xFFC00000)>>22;
|
|
X = priv->pshare->IQKMatrixRegSetting[Indexforchannel].Value[0][0];
|
|
Y = priv->pshare->IQKMatrixRegSetting[Indexforchannel].Value[0][1];
|
|
|
|
if(X != 0)
|
|
{
|
|
if ((X & 0x00000200) != 0)
|
|
X = X | 0xFFFFFC00;
|
|
ele_A = ((X * ele_D)>>8)&0x000003FF;
|
|
|
|
//new element C = element D x Y
|
|
if ((Y & 0x00000200) != 0)
|
|
Y = Y | 0xFFFFFC00;
|
|
ele_C = ((Y * ele_D)>>8)&0x000003FF;
|
|
|
|
//wirte 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(priv, rOFDM0_XATxIQImbalance, bMaskDWord, value32);
|
|
|
|
value32 = (ele_C&0x000003C0)>>6;
|
|
PHY_SetBBReg(priv, rOFDM0_XCTxAFE, bMaskH4Bits, value32);
|
|
|
|
value32 = ((X * ele_D)>>7)&0x01;
|
|
PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(24), value32);
|
|
|
|
}
|
|
else
|
|
{
|
|
PHY_SetBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, OFDMSwingTable[(unsigned char)OFDM_index[0]]);
|
|
PHY_SetBBReg(priv, rOFDM0_XCTxAFE, bMaskH4Bits, 0x00);
|
|
PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(24), 0x00);
|
|
}
|
|
|
|
//printk("TxPwrTracking for path A: X = 0x%x, Y = 0x%x ele_A = 0x%x ele_C = 0x%x ele_D = 0x%x 0xe94 = 0x%x 0xe9c = 0x%x\n",
|
|
//(unsigned int)X, (unsigned int)Y, (unsigned int)ele_A, (unsigned int)ele_C, (unsigned int)ele_D, (unsigned int)X, (unsigned int)Y);
|
|
|
|
{
|
|
//Adjust CCK according to IQK result
|
|
if(!priv->pshare->bCCKinCH14){
|
|
RTL_W8(0xa22, CCKSwingTable_Ch1_Ch13[(unsigned char)CCK_index][0]);
|
|
RTL_W8(0xa23, CCKSwingTable_Ch1_Ch13[(unsigned char)CCK_index][1]);
|
|
RTL_W8(0xa24, CCKSwingTable_Ch1_Ch13[(unsigned char)CCK_index][2]);
|
|
RTL_W8(0xa25, CCKSwingTable_Ch1_Ch13[(unsigned char)CCK_index][3]);
|
|
RTL_W8(0xa26, CCKSwingTable_Ch1_Ch13[(unsigned char)CCK_index][4]);
|
|
RTL_W8(0xa27, CCKSwingTable_Ch1_Ch13[(unsigned char)CCK_index][5]);
|
|
RTL_W8(0xa28, CCKSwingTable_Ch1_Ch13[(unsigned char)CCK_index][6]);
|
|
RTL_W8(0xa29, CCKSwingTable_Ch1_Ch13[(unsigned char)CCK_index][7]);
|
|
}
|
|
else{
|
|
RTL_W8(0xa22, CCKSwingTable_Ch14[(unsigned char)CCK_index][0]);
|
|
RTL_W8(0xa23, CCKSwingTable_Ch14[(unsigned char)CCK_index][1]);
|
|
RTL_W8(0xa24, CCKSwingTable_Ch14[(unsigned char)CCK_index][2]);
|
|
RTL_W8(0xa25, CCKSwingTable_Ch14[(unsigned char)CCK_index][3]);
|
|
RTL_W8(0xa26, CCKSwingTable_Ch14[(unsigned char)CCK_index][4]);
|
|
RTL_W8(0xa27, CCKSwingTable_Ch14[(unsigned char)CCK_index][5]);
|
|
RTL_W8(0xa28, CCKSwingTable_Ch14[(unsigned char)CCK_index][6]);
|
|
RTL_W8(0xa29, CCKSwingTable_Ch14[(unsigned char)CCK_index][7]);
|
|
}
|
|
}
|
|
|
|
if(is2T)
|
|
{
|
|
ele_D = (OFDMSwingTable[(unsigned char)OFDM_index[1]] & 0xFFC00000)>>22;
|
|
|
|
//new element A = element D x X
|
|
X = priv->pshare->IQKMatrixRegSetting[Indexforchannel].Value[0][4];
|
|
Y = priv->pshare->IQKMatrixRegSetting[Indexforchannel].Value[0][5];
|
|
|
|
//if(X != 0 && pHalData->CurrentBandType92D == ODM_BAND_ON_2_4G)
|
|
if((X != 0) && (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G))
|
|
|
|
{
|
|
if ((X & 0x00000200) != 0) //consider minus
|
|
X = X | 0xFFFFFC00;
|
|
ele_A = ((X * ele_D)>>8)&0x000003FF;
|
|
|
|
//new element C = element D x Y
|
|
if ((Y & 0x00000200) != 0)
|
|
Y = Y | 0xFFFFFC00;
|
|
ele_C = ((Y * ele_D)>>8)&0x00003FF;
|
|
|
|
//wirte 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(priv, rOFDM0_XBTxIQImbalance, bMaskDWord, value32);
|
|
|
|
value32 = (ele_C&0x000003C0)>>6;
|
|
PHY_SetBBReg(priv, rOFDM0_XDTxAFE, bMaskH4Bits, value32);
|
|
|
|
value32 = ((X * ele_D)>>7)&0x01;
|
|
PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(28), value32);
|
|
|
|
}
|
|
else
|
|
{
|
|
PHY_SetBBReg(priv, rOFDM0_XBTxIQImbalance, bMaskDWord, OFDMSwingTable[(unsigned char)OFDM_index[1]]);
|
|
PHY_SetBBReg(priv, rOFDM0_XDTxAFE, bMaskH4Bits, 0x00);
|
|
PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(28), 0x00);
|
|
}
|
|
|
|
//printk("TxPwrTracking path B: X = 0x%x, Y = 0x%x ele_A = 0x%x ele_C = 0x%x ele_D = 0x%x 0xeb4 = 0x%x 0xebc = 0x%x\n",
|
|
//(unsigned int)X, (unsigned int)Y, (unsigned int)ele_A, (unsigned int)ele_C, (unsigned int)ele_D, (unsigned int)X, (unsigned int)Y);
|
|
}
|
|
|
|
printk("TxPwrTracking 0xc80 = 0x%x, 0xc94 = 0x%x RF 0x24 = 0x%x\n\n", PHY_QueryBBReg(priv, 0xc80, bMaskDWord), PHY_QueryBBReg(priv, 0xc94, bMaskDWord), PHY_QueryRFReg(priv, RF_PATH_A, 0x24, bRFRegOffsetMask, 1));
|
|
}
|
|
}
|
|
|
|
#if 0 //DO NOT do IQK during 88E power tracking
|
|
// if((delta_IQK > pHalData->Delta_IQK) && (pHalData->Delta_IQK != 0))
|
|
if (delta_IQK >= 8) // Delta temperature is equal to or larger than 20 centigrade.
|
|
{
|
|
ODM_ResetIQKResult(priv);
|
|
|
|
/*
|
|
#if(DM_ODM_SUPPORT_TYPE & ODM_WIN)
|
|
#if (DEV_BUS_TYPE == RT_PCI_INTERFACE)
|
|
#if USE_WORKITEM
|
|
PlatformAcquireMutex(&pHalData->mxChnlBwControl);
|
|
#else
|
|
PlatformAcquireSpinLock(Adapter, RT_CHANNEL_AND_BANDWIDTH_SPINLOCK);
|
|
#endif
|
|
#elif((DEV_BUS_TYPE == RT_USB_INTERFACE) || (DEV_BUS_TYPE == RT_SDIO_INTERFACE))
|
|
PlatformAcquireMutex(&pHalData->mxChnlBwControl);
|
|
#endif
|
|
#endif
|
|
*/
|
|
priv->pshare->ThermalValue_IQK= ThermalValue;
|
|
PHY_IQCalibrate_8188E(priv, FALSE);
|
|
|
|
/*
|
|
#if(DM_ODM_SUPPORT_TYPE & ODM_WIN)
|
|
#if (DEV_BUS_TYPE == RT_PCI_INTERFACE)
|
|
#if USE_WORKITEM
|
|
PlatformReleaseMutex(&pHalData->mxChnlBwControl);
|
|
#else
|
|
PlatformReleaseSpinLock(Adapter, RT_CHANNEL_AND_BANDWIDTH_SPINLOCK);
|
|
#endif
|
|
#elif((DEV_BUS_TYPE == RT_USB_INTERFACE) || (DEV_BUS_TYPE == RT_SDIO_INTERFACE))
|
|
PlatformReleaseMutex(&pHalData->mxChnlBwControl);
|
|
#endif
|
|
#endif
|
|
*/
|
|
}
|
|
#endif
|
|
//update thermal meter value
|
|
if(priv->pshare->TxPowerTrackControl)
|
|
{
|
|
//Adapter->HalFunc.SetHalDefVarHandler(Adapter, HAL_DEF_THERMAL_VALUE, &ThermalValue);
|
|
priv->pshare->ThermalValue = ThermalValue;
|
|
}
|
|
|
|
}
|
|
|
|
//printk("<===dm_TXPowerTrackingCallback_ThermalMeter_8188E\n");
|
|
|
|
priv->pshare->TXPowercount = 0;
|
|
|
|
}
|
|
|
|
|
|
#endif // CALIBRATE_BY_ODM
|
|
|
|
|
|
#endif // CONFIG_RTL_88E_SUPPORT
|
|
|