1 /******************************************************************************
2 *
3 * Copyright(c) 2007 - 2017 Realtek Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * The full GNU General Public License is included in this distribution in the
15 * file called LICENSE.
16 *
17 * Contact Information:
18 * wlanfae <wlanfae@realtek.com>
19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20 * Hsinchu 300, Taiwan.
21 *
22 * Larry Finger <Larry.Finger@lwfinger.net>
23 *
24 *****************************************************************************/
25
26 /*@************************************************************
27 * include files
28 ************************************************************/
29
30 #include "mp_precomp.h"
31 #include "phydm_precomp.h"
32
33 #ifdef PHYDM_CCK_RX_PATHDIV_SUPPORT /* @PHYDM-342*/
phydm_cck_rx_pathdiv_manaul(void * dm_void,boolean en_cck_rx_pathdiv)34 void phydm_cck_rx_pathdiv_manaul(void *dm_void, boolean en_cck_rx_pathdiv)
35 {
36 struct dm_struct *dm = (struct dm_struct *)dm_void;
37
38 /* @Can not apply for 98F/14B/97G from DD YC*/
39 if (en_cck_rx_pathdiv) {
40 odm_set_bb_reg(dm, R_0x1a14, BIT(7), 0x0);
41 odm_set_bb_reg(dm, R_0x1a74, BIT(8), 0x1);
42 } else {
43 odm_set_bb_reg(dm, R_0x1a14, BIT(7), 0x1);
44 odm_set_bb_reg(dm, R_0x1a74, BIT(8), 0x0);
45 }
46 }
47
phydm_cck_rx_pathdiv_watchdog(void * dm_void)48 void phydm_cck_rx_pathdiv_watchdog(void *dm_void)
49 {
50 struct dm_struct *dm = (struct dm_struct *)dm_void;
51 struct phydm_cck_rx_pathdiv *cckrx_t = &dm->dm_cck_rx_pathdiv_table;
52 struct phydm_fa_struct *fa_t = &dm->false_alm_cnt;
53 u8 rssi_th = 0;
54 u32 rssi_a = 0, rssi_b = 0, rssi_avg = 0;
55
56 if (!cckrx_t->en_cck_rx_pathdiv)
57 return;
58
59 rssi_a = PHYDM_DIV(cckrx_t->path_a_sum, cckrx_t->path_a_cnt);
60 rssi_b = PHYDM_DIV(cckrx_t->path_b_sum, cckrx_t->path_b_cnt);
61 rssi_avg = (rssi_a + rssi_b) >> 1;
62
63 pr_debug("Rx-A:%d, Rx-B:%d, avg:%d\n", rssi_a, rssi_b, rssi_avg);
64
65 cckrx_t->path_a_cnt = 0;
66 cckrx_t->path_a_sum = 0;
67 cckrx_t->path_b_cnt = 0;
68 cckrx_t->path_b_sum = 0;
69
70 if (fa_t->cnt_all >= 100)
71 rssi_th = cckrx_t->rssi_fa_th;
72 else
73 rssi_th = cckrx_t->rssi_th;
74
75 if (dm->phy_dbg_info.num_qry_beacon_pkt > 14 && rssi_avg <= rssi_th)
76 phydm_cck_rx_pathdiv_manaul(dm, true);
77 else
78 phydm_cck_rx_pathdiv_manaul(dm, false);
79 }
80
phydm_cck_rx_pathdiv_init(void * dm_void)81 void phydm_cck_rx_pathdiv_init(void *dm_void)
82 {
83 struct dm_struct *dm = (struct dm_struct *)dm_void;
84 struct phydm_cck_rx_pathdiv *cckrx_t = &dm->dm_cck_rx_pathdiv_table;
85
86 cckrx_t->en_cck_rx_pathdiv = false;
87 cckrx_t->path_a_cnt = 0;
88 cckrx_t->path_a_sum = 0;
89 cckrx_t->path_b_cnt = 0;
90 cckrx_t->path_b_sum = 0;
91 cckrx_t->rssi_fa_th = 45;
92 cckrx_t->rssi_th = 25;
93 }
94
phydm_process_rssi_for_cck_rx_pathdiv(void * dm_void,void * phy_info_void,void * pkt_info_void)95 void phydm_process_rssi_for_cck_rx_pathdiv(void *dm_void, void *phy_info_void,
96 void *pkt_info_void)
97 {
98 struct dm_struct *dm = (struct dm_struct *)dm_void;
99 struct phydm_phyinfo_struct *phy_info = NULL;
100 struct phydm_perpkt_info_struct *pktinfo = NULL;
101 struct phydm_cck_rx_pathdiv *cckrx_t = &dm->dm_cck_rx_pathdiv_table;
102
103 phy_info = (struct phydm_phyinfo_struct *)phy_info_void;
104 pktinfo = (struct phydm_perpkt_info_struct *)pkt_info_void;
105
106 if (!(pktinfo->is_packet_to_self || pktinfo->is_packet_match_bssid))
107 return;
108
109 if (pktinfo->is_cck_rate)
110 return;
111
112 cckrx_t->path_a_sum += phy_info->rx_mimo_signal_strength[0];
113 cckrx_t->path_a_cnt++;
114
115 cckrx_t->path_b_sum += phy_info->rx_mimo_signal_strength[1];
116 cckrx_t->path_b_cnt++;
117 }
118
phydm_cck_rx_pathdiv_dbg(void * dm_void,char input[][16],u32 * _used,char * output,u32 * _out_len)119 void phydm_cck_rx_pathdiv_dbg(void *dm_void, char input[][16], u32 *_used,
120 char *output, u32 *_out_len)
121 {
122 struct dm_struct *dm = (struct dm_struct *)dm_void;
123 struct phydm_cck_rx_pathdiv *cckrx_t = &dm->dm_cck_rx_pathdiv_table;
124 char help[] = "-h";
125 u32 var1[10] = {0};
126 u32 used = *_used;
127 u32 out_len = *_out_len;
128 u8 i = 0;
129
130 if (!(dm->support_ic_type & ODM_RTL8822C))
131 return;
132
133 for (i = 0; i < 3; i++) {
134 PHYDM_SSCANF(input[i + 1], DCMD_DECIMAL, &var1[i]);
135 }
136
137 if ((strcmp(input[1], help) == 0)) {
138 PDM_SNPF(out_len, used, output + used, out_len - used,
139 "CCK rx pathdiv manual on: {1} {En}\n");
140 PDM_SNPF(out_len, used, output + used, out_len - used,
141 "CCK rx pathdiv watchdog on: {2} {En}\n");
142 PDM_SNPF(out_len, used, output + used, out_len - used,
143 "CCK rx pathdiv rssi_th : {3} {th} {fa_th}\n");
144 } else if (var1[0] == 1) {
145 if (var1[1] == 1)
146 phydm_cck_rx_pathdiv_manaul(dm, true);
147 else
148 phydm_cck_rx_pathdiv_manaul(dm, false);
149 } else if (var1[0] == 2) {
150 if (var1[1] == 1) {
151 cckrx_t->en_cck_rx_pathdiv = true;
152 } else {
153 cckrx_t->en_cck_rx_pathdiv = false;
154 phydm_cck_rx_pathdiv_manaul(dm, false);
155 }
156 } else if (var1[0] == 3) {
157 cckrx_t->rssi_th = (u8)var1[1];
158 cckrx_t->rssi_fa_th = (u8)var1[2];
159 }
160 *_used = used;
161 *_out_len = out_len;
162 }
163 #endif
164