/****************************************************************************** | |
* | |
* Copyright(c) 2007 - 2017 Realtek Corporation. | |
* | |
* This program is free software; you can redistribute it and/or modify it | |
* under the terms of version 2 of the GNU General Public License as | |
* published by the Free Software Foundation. | |
* | |
* This program is distributed in the hope that it will be useful, but WITHOUT | |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
* more details. | |
* | |
*****************************************************************************/ | |
//============================================================ | |
// include files | |
//============================================================ | |
#include "mp_precomp.h" | |
#include "phydm_precomp.h" | |
#if (DM_ODM_SUPPORT_TYPE & ODM_WIN) | |
#if 0 | |
u32 _sqrt(u64 n) | |
{ | |
u64 ans = 0, q = 0; | |
s64 i; | |
/*for (i = sizeof(n) * 8 - 2; i > -1; i = i - 2) {*/ | |
for (i = 8 * 8 - 2; i > -1; i = i - 2) { | |
q = (q << 2) | ((n & (3 << i)) >> i); | |
if (q >= ((ans << 2) | 1)) | |
{ | |
q = q - ((ans << 2) | 1); | |
ans = (ans << 1) | 1; | |
} | |
else | |
ans = ans << 1; | |
} | |
DbgPrint("ans=0x%x\n", ans); | |
return (u32)ans; | |
} | |
#endif | |
u64 _sqrt(u64 x) | |
{ | |
u64 i = 0; | |
u64 j = x / 2 + 1; | |
while (i <= j) { | |
u64 mid = (i + j) / 2; | |
u64 sq = mid * mid; | |
if (sq == x) | |
return mid; | |
else if (sq < x) | |
i = mid + 1; | |
else | |
j = mid - 1; | |
} | |
return j; | |
} | |
u32 | |
halrf_get_psd_data( | |
void *p_dm_void, | |
u32 point | |
) | |
{ | |
struct PHY_DM_STRUCT *p_dm = (struct PHY_DM_STRUCT *)p_dm_void; | |
struct _hal_rf_ *p_rf = &(p_dm->rf_table); | |
struct _halrf_psd_data *p_psd = &(p_rf->halrf_psd_data); | |
u32 psd_val = 0, psd_reg, psd_report, psd_point, psd_start, i, delay_time; | |
#if (DEV_BUS_TYPE == RT_USB_INTERFACE) || (DEV_BUS_TYPE == RT_SDIO_INTERFACE) | |
if (p_psd->average == 0) | |
delay_time = 100; | |
else | |
delay_time = 0; | |
#else | |
if (p_psd->average == 0) | |
delay_time = 1000; | |
else | |
delay_time = 100; | |
#endif | |
if (p_dm->support_ic_type & (ODM_RTL8812 | ODM_RTL8821 | ODM_RTL8814A | ODM_RTL8822B | ODM_RTL8821C)) { | |
psd_reg = 0x910; | |
psd_report = 0xf44; | |
} else { | |
psd_reg = 0x808; | |
psd_report = 0x8b4; | |
} | |
if (p_dm->support_ic_type & ODM_RTL8710B) { | |
psd_point = 0xeffffc00; | |
psd_start = 0x10000000; | |
} else { | |
psd_point = 0xffbffc00; | |
psd_start = 0x00400000; | |
} | |
psd_val = odm_get_bb_reg(p_dm, psd_reg, MASKDWORD); | |
psd_val &= psd_point; | |
psd_val |= point; | |
odm_set_bb_reg(p_dm, psd_reg, MASKDWORD, psd_val); | |
psd_val |= psd_start; | |
odm_set_bb_reg(p_dm, psd_reg, MASKDWORD, psd_val); | |
for (i = 0; i < delay_time; i++) | |
ODM_delay_us(1); | |
psd_val = odm_get_bb_reg(p_dm, psd_report, MASKDWORD); | |
if (p_dm->support_ic_type & (ODM_RTL8821C | ODM_RTL8710B)) { | |
psd_val &= MASKL3BYTES; | |
psd_val = psd_val / 32; | |
} else | |
psd_val &= MASKLWORD; | |
return psd_val; | |
} | |
void | |
halrf_psd( | |
void *p_dm_void, | |
u32 point, | |
u32 start_point, | |
u32 stop_point, | |
u32 average | |
) | |
{ | |
struct PHY_DM_STRUCT *p_dm = (struct PHY_DM_STRUCT *)p_dm_void; | |
struct _hal_rf_ *p_rf = &(p_dm->rf_table); | |
struct _halrf_psd_data *p_psd = &(p_rf->halrf_psd_data); | |
u32 i = 0, j = 0, k = 0; | |
u32 psd_reg, avg_org, point_temp, average_tmp; | |
u64 data_tatal = 0, data_temp[64] = {0}; | |
p_psd->buf_size = 256; | |
if (average == 0) | |
average_tmp = 1; | |
else | |
average_tmp = average; | |
if (p_dm->support_ic_type & (ODM_RTL8812 | ODM_RTL8821 | ODM_RTL8814A | ODM_RTL8822B | ODM_RTL8821C)) | |
psd_reg = 0x910; | |
else | |
psd_reg = 0x808; | |
#if 0 | |
dbg_print("[PSD]point=%d, start_point=%d, stop_point=%d, average=%d, average_tmp=%d, buf_size=%d\n", | |
point, start_point, stop_point, average, average_tmp, p_psd->buf_size); | |
#endif | |
for (i = 0; i < p_psd->buf_size; i++) | |
p_psd->psd_data[i] = 0; | |
if (p_dm->support_ic_type & ODM_RTL8710B) | |
avg_org = odm_get_bb_reg(p_dm, psd_reg, 0x30000); | |
else | |
avg_org = odm_get_bb_reg(p_dm, psd_reg, 0x3000); | |
if (average != 0) | |
{ | |
if (p_dm->support_ic_type & ODM_RTL8710B) | |
odm_set_bb_reg(p_dm, psd_reg, 0x30000, 0x1); | |
else | |
odm_set_bb_reg(p_dm, psd_reg, 0x3000, 0x1); | |
} | |
#if 0 | |
if (avg_temp == 0) | |
avg = 1; | |
else if (avg_temp == 1) | |
avg = 8; | |
else if (avg_temp == 2) | |
avg = 16; | |
else if (avg_temp == 3) | |
avg = 32; | |
#endif | |
i = start_point; | |
while (i < stop_point) { | |
data_tatal = 0; | |
if (i >= point) | |
point_temp = i - point; | |
else | |
point_temp = i; | |
for (k = 0; k < average_tmp; k++) { | |
data_temp[k] = halrf_get_psd_data(p_dm, point_temp); | |
data_tatal = data_tatal + (data_temp[k] * data_temp[k]); | |
#if 0 | |
if ((k % 20) == 0) | |
dbg_print("\n "); | |
dbg_print("0x%x ", data_temp[k]); | |
#endif | |
} | |
/*dbg_print("\n");*/ | |
data_tatal = ((data_tatal * 100) / average_tmp); | |
p_psd->psd_data[j] = (u32)_sqrt(data_tatal); | |
i++; | |
j++; | |
} | |
#if 0 | |
for (i = 0; i < p_psd->buf_size; i++) { | |
if ((i % 20) == 0) | |
dbg_print("\n "); | |
dbg_print("0x%x ", p_psd->psd_data[i]); | |
} | |
dbg_print("\n\n"); | |
#endif | |
if (p_dm->support_ic_type & ODM_RTL8710B) | |
odm_set_bb_reg(p_dm, psd_reg, 0x30000, avg_org); | |
else | |
odm_set_bb_reg(p_dm, psd_reg, 0x3000, avg_org); | |
} | |
enum rt_status | |
halrf_psd_init( | |
void *p_dm_void | |
) | |
{ | |
enum rt_status ret_status = RT_STATUS_SUCCESS; | |
struct PHY_DM_STRUCT *p_dm = (struct PHY_DM_STRUCT *)p_dm_void; | |
struct _hal_rf_ *p_rf = &(p_dm->rf_table); | |
struct _halrf_psd_data *p_psd = &(p_rf->halrf_psd_data); | |
if (p_psd->psd_progress) | |
ret_status = RT_STATUS_PENDING; | |
else { | |
p_psd->psd_progress = 1; | |
halrf_psd(p_dm, p_psd->point, p_psd->start_point, p_psd->stop_point, p_psd->average); | |
p_psd->psd_progress = 0; | |
} | |
return ret_status; | |
} | |
enum rt_status | |
halrf_psd_query( | |
void *p_dm_void, | |
u32 *outbuf, | |
u32 buf_size | |
) | |
{ | |
enum rt_status ret_status = RT_STATUS_SUCCESS; | |
struct PHY_DM_STRUCT *p_dm = (struct PHY_DM_STRUCT *)p_dm_void; | |
struct _hal_rf_ *p_rf = &(p_dm->rf_table); | |
struct _halrf_psd_data *p_psd = &(p_rf->halrf_psd_data); | |
if (p_psd->psd_progress) | |
ret_status = RT_STATUS_PENDING; | |
else | |
PlatformMoveMemory(outbuf, p_psd->psd_data, 0x400); | |
return ret_status; | |
} | |
enum rt_status | |
halrf_psd_init_query( | |
void *p_dm_void, | |
u32 *outbuf, | |
u32 point, | |
u32 start_point, | |
u32 stop_point, | |
u32 average, | |
u32 buf_size | |
) | |
{ | |
enum rt_status ret_status = RT_STATUS_SUCCESS; | |
struct PHY_DM_STRUCT *p_dm = (struct PHY_DM_STRUCT *)p_dm_void; | |
struct _hal_rf_ *p_rf = &(p_dm->rf_table); | |
struct _halrf_psd_data *p_psd = &(p_rf->halrf_psd_data); | |
p_psd->point = point; | |
p_psd->start_point = start_point; | |
p_psd->stop_point = stop_point; | |
p_psd->average = average; | |
if (p_psd->psd_progress) | |
ret_status = RT_STATUS_PENDING; | |
else { | |
p_psd->psd_progress = 1; | |
halrf_psd(p_dm, p_psd->point, p_psd->start_point, p_psd->stop_point, p_psd->average); | |
PlatformMoveMemory(outbuf, p_psd->psd_data, 0x400); | |
p_psd->psd_progress = 0; | |
} | |
return ret_status; | |
} | |
#endif /*#if (DM_ODM_SUPPORT_TYPE & ODM_WIN)*/ | |