kernel-brax3-ubuntu-touch/drivers/misc/mediatek/ccci_util/ccci_util_md_rat.c
erascape f319b992b1 kernel-5.15: Initial import brax3 UT kernel
* halium configs enabled

Signed-off-by: erascape <erascape@proton.me>
2025-09-23 15:17:10 +00:00

437 lines
10 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2021 MediaTek Inc.
*/
#include "ccci_util_lib_main.h"
/*------------------------------------------*/
#define MD_CAP_BIT_NUM (7)
/*------------------------------------------*/
/* Bit map defination at MD side diff to AP */
/* 0 | 0 | Lf | Lt | W | C | T | G */
#define MD_CAP_GSM (1<<0)
#define MD_CAP_TDS_CDMA (1<<1)
#define MD_CAP_WCDMA (1<<3)
#define MD_CAP_TDD_LTE (1<<4)
#define MD_CAP_FDD_LTE (1<<5)
#define MD_CAP_CDMA2000 (1<<2)
#define MD_CAP_NR (1<<6)
#define MD_CAP_FULL_SET (MD_CAP_GSM|MD_CAP_TDS_CDMA| \
MD_CAP_WCDMA|MD_CAP_TDD_LTE| \
MD_CAP_FDD_LTE|MD_CAP_CDMA2000|MD_CAP_NR)
/* Note: this must keep sync with md_rat_map table.
* If MD_CAP_FULL_SET change or md_rat_map table change, this macro should change too.
*/
#define MD_CAP_FULL_SET_IDX (24)
static const unsigned int md_img_capability_map[] = { /* At check header */
/* 0 - None */
0,
/* 1 - G */
MD_CAP_GSM,
/* 2 - W */
MD_CAP_WCDMA,
/* 3 - WG = W + G */
(MD_CAP_WCDMA|MD_CAP_GSM),
/* 4 - TG = T + G */
(MD_CAP_TDS_CDMA|MD_CAP_GSM),
/* 5 - LWG = Lf + Lt + T + G */
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_GSM),
/* 6 - LTG = Lf + Lt + T + G */
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_TDS_CDMA|MD_CAP_GSM),
/* 7 - SGLTE = Lf + Lt + T + G (Phase out)*/
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_TDS_CDMA|MD_CAP_GSM),
/* 8 - LTG = Lf + Lt + T + G */
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_TDS_CDMA|MD_CAP_GSM),
/* 9 - LWG = Lf + Lt + W + G */
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_GSM),
/* 10 - LWTG = Lf + Lt + W + T + G */
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_TDS_CDMA|MD_CAP_GSM),
/* 11 - LWCG = Lf + Lt + W + C + G */
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_CDMA2000|MD_CAP_GSM),
/* 12 - LWCTG = N + Lf + Lt + W + C + T + G */
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_CDMA2000
|MD_CAP_TDS_CDMA|MD_CAP_GSM),
/* 13 - NLWTG = N + Lf + Lt + W + T + G */
(MD_CAP_NR|MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA
|MD_CAP_TDS_CDMA|MD_CAP_GSM),
/* 14 - NLWCG = N + Lf + Lt + W + C + G */
(MD_CAP_NR|MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA
|MD_CAP_CDMA2000|MD_CAP_GSM),
/* 15 - NL = N + Lf + Lt */
(MD_CAP_NR|MD_CAP_FDD_LTE|MD_CAP_TDD_LTE),
};
static const unsigned int md_rat_map[] = { /* Options supplied by MD */
/* 0 ~ 7 not userd */
0, 0, 0, 0, 0, 0, 0, 0,
/* ultg - 8 */
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_TDS_CDMA|MD_CAP_GSM),
/* ulwg - 9 */
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_GSM),
/* ulwtg - 10 */
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_TDS_CDMA|MD_CAP_GSM),
/* ulwcg - 11 */
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_CDMA2000|MD_CAP_GSM),
/* ulwctg -12 */
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_CDMA2000
|MD_CAP_TDS_CDMA|MD_CAP_GSM),
/* ulttg - 13 */
(MD_CAP_TDD_LTE|MD_CAP_TDS_CDMA|MD_CAP_GSM),
/* ulfwg - 14 */
(MD_CAP_FDD_LTE|MD_CAP_WCDMA|MD_CAP_GSM),
/* ulfwcg - 15 */
(MD_CAP_FDD_LTE|MD_CAP_WCDMA|MD_CAP_CDMA2000|MD_CAP_GSM),
/* ulctg - 16 */
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_CDMA2000|MD_CAP_TDS_CDMA
|MD_CAP_GSM),
/* ultctg - 17 */
(MD_CAP_TDD_LTE|MD_CAP_CDMA2000|MD_CAP_TDS_CDMA|MD_CAP_GSM),
/*ultwg - 18 */
(MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_GSM),
/* ultwcg -19 */
(MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_CDMA2000|MD_CAP_GSM),
/* ulftg - 20 */
(MD_CAP_FDD_LTE|MD_CAP_TDS_CDMA|MD_CAP_GSM),
/* ulfctg - 21 */
(MD_CAP_FDD_LTE|MD_CAP_CDMA2000|MD_CAP_TDS_CDMA|MD_CAP_GSM),
/* unlwg - 22 */
(MD_CAP_NR|MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA
|MD_CAP_GSM),
/* unlwtg - 23 */
(MD_CAP_NR|MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA
|MD_CAP_TDS_CDMA|MD_CAP_GSM),
/* unlwctg - 24 */
(MD_CAP_NR|MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_CDMA2000
|MD_CAP_TDS_CDMA|MD_CAP_GSM),
/* unlwcg - 25 */
(MD_CAP_NR|MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA
|MD_CAP_CDMA2000|MD_CAP_GSM),
/* unltctg - 26 */
(MD_CAP_NR|MD_CAP_TDD_LTE|MD_CAP_CDMA2000
|MD_CAP_TDS_CDMA|MD_CAP_GSM),
/* unl - 27 */
(MD_CAP_NR|MD_CAP_FDD_LTE|MD_CAP_TDD_LTE),
};
static unsigned int get_bit_set_num(unsigned int bitmap)
{
unsigned int i;
unsigned int num = 0;
unsigned int curr_bit = 1;
for (i = 0; i < MD_CAP_BIT_NUM; i++) {
if (bitmap & curr_bit)
num++;
curr_bit = curr_bit << 1;
}
return num;
}
static unsigned int get_rat_id_by_bitmap(unsigned int rat_bit_map)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(md_rat_map); i++) {
if (rat_bit_map == md_rat_map[i])
return i;
}
return 0;
}
static unsigned int find_prefer_val(unsigned int ref_rat, unsigned int *idx)
{
unsigned int i;
unsigned int min_bitmap, min_bitmap_num, num;
unsigned int idx_at_support_list = MD_CAP_FULL_SET_IDX;
for (i = 0; i < ARRAY_SIZE(md_rat_map); i++) {
if (ref_rat == md_rat_map[i]) {
if (idx)
*idx = i;
return ref_rat;
}
}
/* Use the most similar settings */
min_bitmap = MD_CAP_FULL_SET;
min_bitmap_num = get_bit_set_num(min_bitmap);
for (i = 0; i < ARRAY_SIZE(md_rat_map); i++) {
if ((ref_rat & md_rat_map[i]) != ref_rat)
continue;
num = get_bit_set_num(md_rat_map[i]);
if (min_bitmap_num > num) {
min_bitmap = md_rat_map[i];
min_bitmap_num = num;
idx_at_support_list = i;
}
}
if (idx)
*idx = idx_at_support_list;
return min_bitmap;
}
static unsigned int get_capability_bit(char cap_str[])
{
if (cap_str == NULL)
return 0;
if ((strcmp(cap_str, "N") == 0) || (strcmp(cap_str, "n") == 0))
return MD_CAP_NR;
if ((strcmp(cap_str, "LF") == 0) || (strcmp(cap_str, "Lf") == 0)
|| (strcmp(cap_str, "lf") == 0))
return MD_CAP_FDD_LTE;
if ((strcmp(cap_str, "LT") == 0) || (strcmp(cap_str, "Lt") == 0)
|| (strcmp(cap_str, "lt") == 0))
return MD_CAP_TDD_LTE;
if ((strcmp(cap_str, "W") == 0) || (strcmp(cap_str, "w") == 0))
return MD_CAP_WCDMA;
if ((strcmp(cap_str, "C") == 0) || (strcmp(cap_str, "c") == 0))
return MD_CAP_CDMA2000;
if ((strcmp(cap_str, "T") == 0) || (strcmp(cap_str, "t") == 0))
return MD_CAP_TDS_CDMA;
if ((strcmp(cap_str, "G") == 0) || (strcmp(cap_str, "g") == 0))
return MD_CAP_GSM;
return 0;
}
#define MAX_CAP_STR_LENGTH 64
static unsigned int ccci_rat_str_to_bitmap(char str[])
{
char tmp_str[MAX_CAP_STR_LENGTH];
unsigned int tmp_str_curr_pos = 0;
unsigned int bitmap = 0;
int str_len;
int i;
if (str == NULL)
return 0;
str_len = strlen(str);
for (i = 0; i < str_len; i++) {
if (str[i] == ' ')
continue;
if (str[i] == '\t')
continue;
if ((str[i] == '/') || (str[i] == '\\') || (str[i] == '_')) {
if (tmp_str_curr_pos) {
tmp_str[tmp_str_curr_pos] = 0;
bitmap |= get_capability_bit(tmp_str);
}
tmp_str_curr_pos = 0;
continue;
}
if (tmp_str_curr_pos < (MAX_CAP_STR_LENGTH-1)) {
tmp_str[tmp_str_curr_pos] = str[i];
tmp_str_curr_pos++;
} else
break;
}
if (tmp_str_curr_pos) {
tmp_str[tmp_str_curr_pos] = 0;
bitmap |= get_capability_bit(tmp_str);
}
return bitmap;
}
unsigned int mtk_ccci_get_md_img_cap(void)
{
unsigned int value = 0;
if (mtk_ccci_find_args_val("md_capability", (unsigned char *)&value, sizeof(unsigned int))
!= sizeof(unsigned int))
pr_info("ccci: %s: get MD CAP fail\n", __func__);
return value;
}
EXPORT_SYMBOL(mtk_ccci_get_md_img_cap);
unsigned int get_md_bin_capability(void)
{
int img_type;
img_type = get_md_img_type();
if (img_type < 0)
return 0;
if (img_type < ARRAY_SIZE(md_img_capability_map))
return md_img_capability_map[img_type];
return 0;
}
EXPORT_SYMBOL(get_md_bin_capability);
int check_rat_at_md_img(char str[])
{
unsigned int rat, cap;
rat = get_capability_bit(str);
cap = get_md_bin_capability();
if (rat & cap)
return 1;
return 0;
}
EXPORT_SYMBOL(check_rat_at_md_img);
static unsigned int s_md_rt_wm_id_bitmap;
static unsigned int s_md_rt_wm_id;
void set_soc_md_rt_rat(unsigned int bitmap, unsigned int id)
{
s_md_rt_wm_id_bitmap = bitmap;
s_md_rt_wm_id = id;
}
EXPORT_SYMBOL(set_soc_md_rt_rat);
unsigned int get_soc_md_rt_rat(void)
{
return s_md_rt_wm_id_bitmap;
}
EXPORT_SYMBOL(get_soc_md_rt_rat);
unsigned int get_soc_md_rt_rat_idx(void)
{
return s_md_rt_wm_id;
}
EXPORT_SYMBOL(get_soc_md_rt_rat_idx);
int check_rat_at_rt_setting(char str[])
{
unsigned int rat, cap;
rat = get_capability_bit(str);
cap = get_soc_md_rt_rat();
if (rat & cap)
return 1;
return 0;
}
EXPORT_SYMBOL(check_rat_at_rt_setting);
int set_soc_md_rt_rat_by_idx(unsigned int wm_idx)
{
unsigned int rat_bitmap, cap;
cap = get_md_bin_capability();
if (!wm_idx)
return -1;
if (wm_idx >= ARRAY_SIZE(md_rat_map)) {
pr_info("CCCI: %s get not support wm_idx:%u\n", __func__, wm_idx);
return -1;
}
rat_bitmap = md_rat_map[wm_idx];
if (!rat_bitmap) {
pr_info("CCCI: %s get invalid wm_idx:%u\n", __func__, wm_idx);
return -1;
}
if ((rat_bitmap & cap) != rat_bitmap) {
pr_info("CCCI:%s: md img cap not support wm_idx: %u [c:0x%x|s:0x%x]\n",
__func__, wm_idx, cap, rat_bitmap);
return -1;
}
set_soc_md_rt_rat(rat_bitmap, wm_idx);
pr_info("CCCI:%s:wm_idx[%u][c:0x%x|s:0x%x]\n", __func__, wm_idx, cap, rat_bitmap);
return 0;
}
EXPORT_SYMBOL(set_soc_md_rt_rat_by_idx);
int set_soc_md_rt_rat_str(char str[])
{
unsigned int rat_bitmap, prefer, cap, id;
cap = get_md_bin_capability();
id = get_rat_id_by_bitmap(cap);
if (id == 0) {
pr_info("CCCI: %s: should not run to here. MD cap not in support list!\n",
__func__);
return -1;
}
if (!str) {
pr_info("CCCI: %s get NULL ptr!\n", __func__);
set_soc_md_rt_rat(cap, id);
return 1;
}
if (strlen(str) == 0) {
pr_info("CCCI: %s str empty, set default value!\n", __func__);
set_soc_md_rt_rat(cap, id);
return 1;
}
rat_bitmap = ccci_rat_str_to_bitmap(str);
prefer = find_prefer_val(rat_bitmap, &id);
if ((prefer == 0) || ((prefer & cap) != prefer)) {
pr_info("CCCI:%s:rat[%s](r:0x%x|p:0x%x|c:0x%x) not support!\n",
__func__, str, rat_bitmap, prefer, cap);
set_soc_md_rt_rat(cap, id);
return 1;
}
set_soc_md_rt_rat(prefer, id);
pr_info("CCCI:%s:rat[%s](r:0x%x|p:0x%x|c:0x%x)[%u]\n",
__func__, str, rat_bitmap, prefer, cap, id);
return 0;
}
EXPORT_SYMBOL(set_soc_md_rt_rat_str);