xref: /freebsd/sys/contrib/dev/rtw89/util.c (revision 6d67aabd63555ab62a2f2b7f52a75ef100a2fe75)
1*6d67aabdSBjoern A. Zeeb // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2*6d67aabdSBjoern A. Zeeb /* Copyright(c) 2024  Realtek Corporation
3*6d67aabdSBjoern A. Zeeb  */
4*6d67aabdSBjoern A. Zeeb 
5*6d67aabdSBjoern A. Zeeb #include "util.h"
6*6d67aabdSBjoern A. Zeeb 
7*6d67aabdSBjoern A. Zeeb #define FRAC_ROWS 3
8*6d67aabdSBjoern A. Zeeb #define FRAC_ROW_MAX (FRAC_ROWS - 1)
9*6d67aabdSBjoern A. Zeeb #define NORM_ROW_MIN FRAC_ROWS
10*6d67aabdSBjoern A. Zeeb 
11*6d67aabdSBjoern A. Zeeb static const u32 db_invert_table[12][8] = {
12*6d67aabdSBjoern A. Zeeb 	/* rows 0~2 in unit of U(32,3) */
13*6d67aabdSBjoern A. Zeeb 	{10, 13, 16, 20, 25, 32, 40, 50},
14*6d67aabdSBjoern A. Zeeb 	{64, 80, 101, 128, 160, 201, 256, 318},
15*6d67aabdSBjoern A. Zeeb 	{401, 505, 635, 800, 1007, 1268, 1596, 2010},
16*6d67aabdSBjoern A. Zeeb 	/* rows 3~11 in unit of U(32,0) */
17*6d67aabdSBjoern A. Zeeb 	{316, 398, 501, 631, 794, 1000, 1259, 1585},
18*6d67aabdSBjoern A. Zeeb 	{1995, 2512, 3162, 3981, 5012, 6310, 7943, 10000},
19*6d67aabdSBjoern A. Zeeb 	{12589, 15849, 19953, 25119, 31623, 39811, 50119, 63098},
20*6d67aabdSBjoern A. Zeeb 	{79433, 100000, 125893, 158489, 199526, 251189, 316228, 398107},
21*6d67aabdSBjoern A. Zeeb 	{501187, 630957, 794328, 1000000, 1258925, 1584893, 1995262, 2511886},
22*6d67aabdSBjoern A. Zeeb 	{3162278, 3981072, 5011872, 6309573, 7943282, 1000000, 12589254,
23*6d67aabdSBjoern A. Zeeb 	 15848932},
24*6d67aabdSBjoern A. Zeeb 	{19952623, 25118864, 31622777, 39810717, 50118723, 63095734, 79432823,
25*6d67aabdSBjoern A. Zeeb 	 100000000},
26*6d67aabdSBjoern A. Zeeb 	{125892541, 158489319, 199526232, 251188643, 316227766, 398107171,
27*6d67aabdSBjoern A. Zeeb 	 501187234, 630957345},
28*6d67aabdSBjoern A. Zeeb 	{794328235, 1000000000, 1258925412, 1584893192, 1995262315, 2511886432U,
29*6d67aabdSBjoern A. Zeeb 	 3162277660U, 3981071706U},
30*6d67aabdSBjoern A. Zeeb };
31*6d67aabdSBjoern A. Zeeb 
32*6d67aabdSBjoern A. Zeeb u32 rtw89_linear_2_db(u64 val)
33*6d67aabdSBjoern A. Zeeb {
34*6d67aabdSBjoern A. Zeeb 	u8 i, j;
35*6d67aabdSBjoern A. Zeeb 	u32 dB;
36*6d67aabdSBjoern A. Zeeb 
37*6d67aabdSBjoern A. Zeeb 	for (i = 0; i < 12; i++) {
38*6d67aabdSBjoern A. Zeeb 		for (j = 0; j < 8; j++) {
39*6d67aabdSBjoern A. Zeeb 			if (i <= FRAC_ROW_MAX &&
40*6d67aabdSBjoern A. Zeeb 			    (val << RTW89_LINEAR_FRAC_BITS) <= db_invert_table[i][j])
41*6d67aabdSBjoern A. Zeeb 				goto cnt;
42*6d67aabdSBjoern A. Zeeb 			else if (i > FRAC_ROW_MAX && val <= db_invert_table[i][j])
43*6d67aabdSBjoern A. Zeeb 				goto cnt;
44*6d67aabdSBjoern A. Zeeb 		}
45*6d67aabdSBjoern A. Zeeb 	}
46*6d67aabdSBjoern A. Zeeb 
47*6d67aabdSBjoern A. Zeeb 	return 96; /* maximum 96 dB */
48*6d67aabdSBjoern A. Zeeb 
49*6d67aabdSBjoern A. Zeeb cnt:
50*6d67aabdSBjoern A. Zeeb 	/* special cases */
51*6d67aabdSBjoern A. Zeeb 	if (j == 0 && i == 0)
52*6d67aabdSBjoern A. Zeeb 		goto end;
53*6d67aabdSBjoern A. Zeeb 
54*6d67aabdSBjoern A. Zeeb 	if (i == NORM_ROW_MIN && j == 0) {
55*6d67aabdSBjoern A. Zeeb 		if (db_invert_table[NORM_ROW_MIN][0] - val >
56*6d67aabdSBjoern A. Zeeb 		    val - (db_invert_table[FRAC_ROW_MAX][7] >> RTW89_LINEAR_FRAC_BITS)) {
57*6d67aabdSBjoern A. Zeeb 			i = FRAC_ROW_MAX;
58*6d67aabdSBjoern A. Zeeb 			j = 7;
59*6d67aabdSBjoern A. Zeeb 		}
60*6d67aabdSBjoern A. Zeeb 		goto end;
61*6d67aabdSBjoern A. Zeeb 	}
62*6d67aabdSBjoern A. Zeeb 
63*6d67aabdSBjoern A. Zeeb 	if (i <= FRAC_ROW_MAX)
64*6d67aabdSBjoern A. Zeeb 		val <<= RTW89_LINEAR_FRAC_BITS;
65*6d67aabdSBjoern A. Zeeb 
66*6d67aabdSBjoern A. Zeeb 	/* compare difference to get precise dB */
67*6d67aabdSBjoern A. Zeeb 	if (j == 0) {
68*6d67aabdSBjoern A. Zeeb 		if (db_invert_table[i][j] - val >
69*6d67aabdSBjoern A. Zeeb 		    val - db_invert_table[i - 1][7]) {
70*6d67aabdSBjoern A. Zeeb 			i--;
71*6d67aabdSBjoern A. Zeeb 			j = 7;
72*6d67aabdSBjoern A. Zeeb 		}
73*6d67aabdSBjoern A. Zeeb 	} else {
74*6d67aabdSBjoern A. Zeeb 		if (db_invert_table[i][j] - val >
75*6d67aabdSBjoern A. Zeeb 		    val - db_invert_table[i][j - 1]) {
76*6d67aabdSBjoern A. Zeeb 			j--;
77*6d67aabdSBjoern A. Zeeb 		}
78*6d67aabdSBjoern A. Zeeb 	}
79*6d67aabdSBjoern A. Zeeb end:
80*6d67aabdSBjoern A. Zeeb 	dB = (i << 3) + j + 1;
81*6d67aabdSBjoern A. Zeeb 
82*6d67aabdSBjoern A. Zeeb 	return dB;
83*6d67aabdSBjoern A. Zeeb }
84*6d67aabdSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_linear_2_db);
85*6d67aabdSBjoern A. Zeeb 
86*6d67aabdSBjoern A. Zeeb u64 rtw89_db_2_linear(u32 db)
87*6d67aabdSBjoern A. Zeeb {
88*6d67aabdSBjoern A. Zeeb 	u64 linear;
89*6d67aabdSBjoern A. Zeeb 	u8 i, j;
90*6d67aabdSBjoern A. Zeeb 
91*6d67aabdSBjoern A. Zeeb 	if (db > 96)
92*6d67aabdSBjoern A. Zeeb 		db = 96;
93*6d67aabdSBjoern A. Zeeb 	else if (db < 1)
94*6d67aabdSBjoern A. Zeeb 		return 1;
95*6d67aabdSBjoern A. Zeeb 
96*6d67aabdSBjoern A. Zeeb 	i = (db - 1) >> 3;
97*6d67aabdSBjoern A. Zeeb 	j = (db - 1) & 0x7;
98*6d67aabdSBjoern A. Zeeb 
99*6d67aabdSBjoern A. Zeeb 	linear = db_invert_table[i][j];
100*6d67aabdSBjoern A. Zeeb 
101*6d67aabdSBjoern A. Zeeb 	if (i >= NORM_ROW_MIN)
102*6d67aabdSBjoern A. Zeeb 		linear = linear << RTW89_LINEAR_FRAC_BITS;
103*6d67aabdSBjoern A. Zeeb 
104*6d67aabdSBjoern A. Zeeb 	return linear;
105*6d67aabdSBjoern A. Zeeb }
106*6d67aabdSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_db_2_linear);
107