summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/realtek/rtw89/util.c
blob: e71956ce985377b1122f381cf505d26870359867 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2024  Realtek Corporation
 */

#include "util.h"

#define FRAC_ROWS 3
#define FRAC_ROW_MAX (FRAC_ROWS - 1)
#define NORM_ROW_MIN FRAC_ROWS

static const u32 db_invert_table[12][8] = {
	/* rows 0~2 in unit of U(32,3) */
	{10, 13, 16, 20, 25, 32, 40, 50},
	{64, 80, 101, 128, 160, 201, 256, 318},
	{401, 505, 635, 800, 1007, 1268, 1596, 2010},
	/* rows 3~11 in unit of U(32,0) */
	{316, 398, 501, 631, 794, 1000, 1259, 1585},
	{1995, 2512, 3162, 3981, 5012, 6310, 7943, 10000},
	{12589, 15849, 19953, 25119, 31623, 39811, 50119, 63098},
	{79433, 100000, 125893, 158489, 199526, 251189, 316228, 398107},
	{501187, 630957, 794328, 1000000, 1258925, 1584893, 1995262, 2511886},
	{3162278, 3981072, 5011872, 6309573, 7943282, 1000000, 12589254,
	 15848932},
	{19952623, 25118864, 31622777, 39810717, 50118723, 63095734, 79432823,
	 100000000},
	{125892541, 158489319, 199526232, 251188643, 316227766, 398107171,
	 501187234, 630957345},
	{794328235, 1000000000, 1258925412, 1584893192, 1995262315, 2511886432U,
	 3162277660U, 3981071706U},
};

u32 rtw89_linear_2_db(u64 val)
{
	u8 i, j;
	u32 dB;

	for (i = 0; i < 12; i++) {
		for (j = 0; j < 8; j++) {
			if (i <= FRAC_ROW_MAX &&
			    (val << RTW89_LINEAR_FRAC_BITS) <= db_invert_table[i][j])
				goto cnt;
			else if (i > FRAC_ROW_MAX && val <= db_invert_table[i][j])
				goto cnt;
		}
	}

	return 96; /* maximum 96 dB */

cnt:
	/* special cases */
	if (j == 0 && i == 0)
		goto end;

	if (i == NORM_ROW_MIN && j == 0) {
		if (db_invert_table[NORM_ROW_MIN][0] - val >
		    val - (db_invert_table[FRAC_ROW_MAX][7] >> RTW89_LINEAR_FRAC_BITS)) {
			i = FRAC_ROW_MAX;
			j = 7;
		}
		goto end;
	}

	if (i <= FRAC_ROW_MAX)
		val <<= RTW89_LINEAR_FRAC_BITS;

	/* compare difference to get precise dB */
	if (j == 0) {
		if (db_invert_table[i][j] - val >
		    val - db_invert_table[i - 1][7]) {
			i--;
			j = 7;
		}
	} else {
		if (db_invert_table[i][j] - val >
		    val - db_invert_table[i][j - 1]) {
			j--;
		}
	}
end:
	dB = (i << 3) + j + 1;

	return dB;
}
EXPORT_SYMBOL(rtw89_linear_2_db);

u64 rtw89_db_2_linear(u32 db)
{
	u64 linear;
	u8 i, j;

	if (db > 96)
		db = 96;
	else if (db < 1)
		return 1;

	i = (db - 1) >> 3;
	j = (db - 1) & 0x7;

	linear = db_invert_table[i][j];

	if (i >= NORM_ROW_MIN)
		linear = linear << RTW89_LINEAR_FRAC_BITS;

	return linear;
}
EXPORT_SYMBOL(rtw89_db_2_linear);