// 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);