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