xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8723ds/hal/phydm/phydm_math_lib.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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 const u32 db_invert_table[12][8] = {
34 	{10, 13, 16, 20, 25, 32, 40, 50}, /* @U(32,3) */
35 	{64, 80, 101, 128, 160, 201, 256, 318}, /* @U(32,3) */
36 	{401, 505, 635, 800, 1007, 1268, 1596, 2010}, /* @U(32,3) */
37 	{316, 398, 501, 631, 794, 1000, 1259, 1585}, /* @U(32,0) */
38 	{1995, 2512, 3162, 3981, 5012, 6310, 7943, 10000}, /* @U(32,0) */
39 	{12589, 15849, 19953, 25119, 31623, 39811, 50119, 63098}, /* @U(32,0) */
40 	{79433, 100000, 125893, 158489, 199526, 251189, 316228,
41 	 398107}, /* @U(32,0) */
42 	{501187, 630957, 794328, 1000000, 1258925, 1584893, 1995262,
43 	 2511886}, /* @U(32,0) */
44 	{3162278, 3981072, 5011872, 6309573, 7943282, 1000000, 12589254,
45 	 15848932}, /* @U(32,0) */
46 	{19952623, 25118864, 31622777, 39810717, 50118723, 63095734,
47 	 79432823, 100000000}, /* @U(32,0) */
48 	{125892541, 158489319, 199526232, 251188643, 316227766, 398107171,
49 	 501187234, 630957345}, /* @U(32,0) */
50 	{794328235, 1000000000, 1258925412, 1584893192, 1995262315,
51 	 2511886432U, 3162277660U, 3981071706U} }; /* @U(32,0) */
52 
53 /*Y = 10*log(X)*/
odm_pwdb_conversion(s32 X,u32 total_bit,u32 decimal_bit)54 s32 odm_pwdb_conversion(s32 X, u32 total_bit, u32 decimal_bit)
55 {
56 	s32 Y, integer = 0, decimal = 0;
57 	u32 i;
58 
59 	if (X == 0)
60 		X = 1; /* @log2(x), x can't be 0 */
61 
62 	for (i = (total_bit - 1); i > 0; i--) {
63 		if (X & BIT(i)) {
64 			integer = i;
65 			if (i > 0) {
66 				/*decimal is 0.5dB*3=1.5dB~=2dB */
67 				decimal = (X & BIT(i - 1)) ? 2 : 0;
68 			}
69 			break;
70 		}
71 	}
72 
73 	Y = 3 * (integer - decimal_bit) + decimal; /* @10*log(x)=3*log2(x), */
74 
75 	return Y;
76 }
77 
odm_sign_conversion(s32 value,u32 total_bit)78 s32 odm_sign_conversion(s32 value, u32 total_bit)
79 {
80 	if (value & BIT(total_bit - 1))
81 		value -= BIT(total_bit);
82 
83 	return value;
84 }
85 
86 /*threshold must form low to high*/
phydm_find_intrvl(void * dm_void,u16 val,u16 * threshold,u16 th_len)87 u16 phydm_find_intrvl(void *dm_void, u16 val, u16 *threshold, u16 th_len)
88 {
89 	struct dm_struct *dm = (struct dm_struct *)dm_void;
90 	u16 i = 0;
91 	u16 ret_val = 0;
92 	u16 max_th = threshold[th_len - 1];
93 
94 	for (i = 0; i < th_len; i++) {
95 		if (val < threshold[i]) {
96 			ret_val = i;
97 			break;
98 		} else if (val >= max_th) {
99 			ret_val = th_len;
100 			break;
101 		}
102 	}
103 
104 	return ret_val;
105 }
106 
phydm_seq_sorting(void * dm_void,u32 * value,u32 * rank_idx,u32 * idx_out,u8 seq_length)107 void phydm_seq_sorting(void *dm_void, u32 *value, u32 *rank_idx, u32 *idx_out,
108 		       u8 seq_length)
109 {
110 	u8 i = 0, j = 0;
111 	u32 tmp_a, tmp_b;
112 	u32 tmp_idx_a, tmp_idx_b;
113 
114 	for (i = 0; i < seq_length; i++)
115 		rank_idx[i] = i;
116 
117 	for (i = 0; i < (seq_length - 1); i++) {
118 		for (j = 0; j < (seq_length - 1 - i); j++) {
119 			tmp_a = value[j];
120 			tmp_b = value[j + 1];
121 
122 			tmp_idx_a = rank_idx[j];
123 			tmp_idx_b = rank_idx[j + 1];
124 
125 			if (tmp_a < tmp_b) {
126 				value[j] = tmp_b;
127 				value[j + 1] = tmp_a;
128 
129 				rank_idx[j] = tmp_idx_b;
130 				rank_idx[j + 1] = tmp_idx_a;
131 			}
132 		}
133 	}
134 
135 	for (i = 0; i < seq_length; i++)
136 		idx_out[rank_idx[i]] = i + 1;
137 }
138 
odm_convert_to_db(u64 value)139 u32 odm_convert_to_db(u64 value)
140 {
141 	u8 i;
142 	u8 j;
143 	u32 dB;
144 
145 	if (value >= db_invert_table[11][7])
146 		return 96; /* @maximum 96 dB */
147 
148 	for (i = 0; i < 12; i++) {
149 		if (i <= 2 && (value << FRAC_BITS) <= db_invert_table[i][7])
150 			break;
151 		else if (i > 2 && value <= db_invert_table[i][7])
152 			break;
153 	}
154 
155 	for (j = 0; j < 8; j++) {
156 		if (i <= 2 && (value << FRAC_BITS) <= db_invert_table[i][j])
157 			break;
158 		else if (i > 2 && i < 12 && value <= db_invert_table[i][j])
159 			break;
160 	}
161 
162 	/*special cases*/
163 	if (j == 0 && i == 0)
164 		goto end;
165 
166 	if (i == 3 && j == 0) {
167 		if (db_invert_table[3][0] - value >
168 		    value - (db_invert_table[2][7] >> FRAC_BITS)) {
169 			i = 2;
170 			j = 7;
171 		}
172 		goto end;
173 	}
174 
175 	if (i < 3)
176 		value = value << FRAC_BITS; /*@elements of row 0~2 shift left*/
177 
178 	/*compare difference to get precise dB*/
179 	if (j == 0) {
180 		if (db_invert_table[i][j] - value >
181 		    value - db_invert_table[i - 1][7]) {
182 			i = i - 1;
183 			j = 7;
184 		}
185 	} else {
186 		if (db_invert_table[i][j] - value >
187 		    value - db_invert_table[i][j - 1]) {
188 			j = j - 1;
189 		}
190 	}
191 end:
192 	dB = (i << 3) + j + 1;
193 
194 	return dB;
195 }
196 
phydm_db_2_linear(u32 value)197 u64 phydm_db_2_linear(u32 value)
198 {
199 	u8 i = 0;
200 	u8 j = 0;
201 	u64 linear = 0;
202 
203 	value = value & 0xFF;
204 
205 	/* @1dB~96dB */
206 	if (value > 96) {
207 		value = 96;
208 	} else if (value < 1) {
209 		linear = 1;
210 		return linear;
211 	}
212 
213 	i = (u8)((value - 1) >> 3);
214 	j = (u8)(value - 1) - (i << 3);
215 
216 	linear = db_invert_table[i][j];
217 
218 	if (i > 2)
219 		linear = linear << FRAC_BITS;
220 
221 	return linear;
222 }
223 
phydm_show_fraction_num(u32 frac_val,u8 bit_num)224 u16 phydm_show_fraction_num(u32 frac_val, u8 bit_num)
225 {
226 	u8 i = 0;
227 	u16 val = 0;
228 	u16 base = 5000;
229 
230 	for (i = bit_num; i > 0; i--) {
231 		if (frac_val & BIT(i - 1))
232 			val += (base >> (bit_num - i));
233 	}
234 	return val;
235 }
236 
phydm_ones_num_in_bitmap(u64 val,u8 size)237 u16 phydm_ones_num_in_bitmap(u64 val, u8 size)
238 {
239 	u8 i = 0;
240 	u8 ones_num = 0;
241 
242 	for (i = 0; i < size; i++) {
243 		if (val & BIT(0))
244 			ones_num++;
245 
246 		val = val >> 1;
247 	}
248 
249 	return ones_num;
250 }
251 
phydm_gen_bitmask(u8 mask_num)252 u64 phydm_gen_bitmask(u8 mask_num)
253 {
254 	u8 i = 0;
255 	u64 bitmask = 0;
256 
257 	if (mask_num > 64)
258 		return 1;
259 
260 	for (i = 0; i < mask_num; i++)
261 		bitmask = (bitmask << 1) | BIT(0);
262 
263 	return bitmask;
264 }
265 
phydm_cnvrt_2_sign(u32 val,u8 bit_num)266 s32 phydm_cnvrt_2_sign(u32 val, u8 bit_num)
267 {
268 	if (bit_num >= 32)
269 		return (s32)val;
270 
271 	if (val & BIT(bit_num - 1)) /*Sign BIT*/
272 		val -= (1 << bit_num); /*@2's*/
273 
274 	return val;
275 }
276 
phydm_cnvrt_2_sign_64(u64 val,u8 bit_num)277 s64 phydm_cnvrt_2_sign_64(u64 val, u8 bit_num)
278 {
279 	u64 one = 1;
280 	s64 val_sign = (s64)val;
281 
282 	if (bit_num >= 64)
283 		return (s64)val;
284 
285 	if (val & (one << (bit_num - 1))) /*Sign BIT*/
286 		val_sign = val - (one << bit_num); /*@2's*/
287 
288 	return val_sign;
289 }
290 
291