ccci_ld_md_tel.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848
  1. /* Copyright Statement:
  2. *
  3. * This software/firmware and related documentation ("MediaTek Software") are
  4. * protected under relevant copyright laws. The information contained herein
  5. * is confidential and proprietary to MediaTek Inc. and/or its licensors.
  6. * Without the prior written permission of MediaTek inc. and/or its licensors,
  7. * any reproduction, modification, use or disclosure of MediaTek Software,
  8. * and information contained herein, in whole or in part, shall be strictly prohibited.
  9. */
  10. /* MediaTek Inc. (C) 2015. All rights reserved.
  11. *
  12. * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  13. * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
  14. * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
  15. * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
  18. * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
  19. * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
  20. * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
  21. * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
  22. * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
  23. * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
  24. * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
  25. * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
  26. * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
  27. * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
  28. * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
  29. * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
  30. */
  31. #include <sys/types.h>
  32. #include <stdint.h>
  33. #include <platform/partition.h>
  34. #include <platform/mt_typedefs.h>
  35. #include <platform/boot_mode.h>
  36. #include <platform/mt_reg_base.h>
  37. #include <platform/errno.h>
  38. #include <printf.h>
  39. #include <string.h>
  40. #include <malloc.h>
  41. #include <libfdt.h>
  42. #include <platform/mt_gpt.h>
  43. #include <debug.h>
  44. #include "ccci_ld_md_core.h"
  45. #include "ccci_ld_md_errno.h"
  46. #include <lk_load_md_wrapper.h>
  47. #include <fdt_op.h>
  48. #define MODULE_NAME "LK_LD_MD"
  49. /***************************************************************************************************
  50. ** Sub section:
  51. ** Telephony operation parsing and prepare part
  52. ***************************************************************************************************/
  53. /* For the following option setting, please check config.h after build, or $project.mk */
  54. #ifdef MTK_C2K_LTE_MODE
  55. #define C2K_LTE_MODE (MTK_C2K_LTE_MODE)
  56. #else
  57. #define C2K_LTE_MODE (0)
  58. #endif
  59. #ifdef MTK_PROTOCOL1_RAT_CONFIG
  60. #define PS1_RAT_DEFAULT MTK_PROTOCOL1_RAT_CONFIG
  61. #else
  62. #define PS1_RAT_DEFAULT ""
  63. #endif
  64. static char *get_lk_ro_env_str(char *name)
  65. {
  66. char *(*NULL_FP)(char *) = 0;
  67. if (NULL_FP == get_ro_env) {
  68. ALWAYS_LOG("dummy get_ro_env\n");
  69. return NULL;
  70. }
  71. return get_ro_env(name);
  72. }
  73. /* Legacy capability table */
  74. #define LEGACY_UBIN_START_ID (8)
  75. static const unsigned int legacy_ubin_rat_map[] = {
  76. (MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_TDS_CDMA|MD_CAP_GSM), /* ultg */
  77. (MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_GSM), /* ulwg */
  78. (MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_TDS_CDMA|MD_CAP_GSM), /* ulwtg */
  79. (MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_CDMA2000|MD_CAP_GSM), /* ulwcg */
  80. (MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_CDMA2000|MD_CAP_TDS_CDMA|MD_CAP_GSM), /* ulwctg */
  81. (MD_CAP_TDD_LTE|MD_CAP_TDS_CDMA|MD_CAP_GSM), /* ulttg */
  82. (MD_CAP_FDD_LTE|MD_CAP_WCDMA|MD_CAP_GSM), /* ulfwg */
  83. (MD_CAP_FDD_LTE|MD_CAP_WCDMA|MD_CAP_CDMA2000|MD_CAP_GSM), /* ulfwcg */
  84. (MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_CDMA2000|MD_CAP_TDS_CDMA|MD_CAP_GSM), /* ulctg */
  85. (MD_CAP_TDD_LTE|MD_CAP_CDMA2000|MD_CAP_TDS_CDMA|MD_CAP_GSM), /* ultctg */
  86. (MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_GSM), /*ultwg */
  87. (MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_CDMA2000|MD_CAP_GSM), /* ultwcg */
  88. (MD_CAP_FDD_LTE|MD_CAP_TDS_CDMA|MD_CAP_GSM), /* ulftg */
  89. (MD_CAP_FDD_LTE|MD_CAP_CDMA2000|MD_CAP_TDS_CDMA|MD_CAP_GSM)/* ulfctg */
  90. };
  91. /* Specail case convert map table source */
  92. static const unsigned int ubin_convert_table_src[] = {
  93. (MD_CAP_GSM|MD_CAP_TDD_LTE|MD_CAP_FDD_LTE|MD_CAP_CDMA2000),
  94. (MD_CAP_GSM|MD_CAP_WCDMA|MD_CAP_CDMA2000)
  95. };
  96. /* Specail case convert map table destination */
  97. static const unsigned int ubin_convert_table_des[] = {
  98. (MD_CAP_GSM|MD_CAP_WCDMA|MD_CAP_TDD_LTE|MD_CAP_FDD_LTE|MD_CAP_CDMA2000),
  99. (MD_CAP_GSM|MD_CAP_WCDMA|MD_CAP_TDD_LTE|MD_CAP_FDD_LTE|MD_CAP_CDMA2000)
  100. };
  101. enum md_type {
  102. md_type_2g = 1,
  103. md_type_3g,
  104. md_type_wg,
  105. md_type_tg,
  106. md_type_lwg,
  107. md_type_ltg,
  108. };
  109. /**************************************************************************************************************/
  110. /* Global variable or table at this file */
  111. /**************************************************************************************************************/
  112. static struct opt_cfg default_option_list[] = { /* string lenght should less then 32 */
  113. {"opt_md1_support", 0},/* if MD1_SUPPORT > 0, MD1_EN true */
  114. {"opt_md3_support", 0},/* if MD3_SUPPORT > 0, MD3_EN true, ECCCI_C2K true, C2K_SUPPORT true */
  115. {"opt_c2k_lte_mode", C2K_LTE_MODE},/* mode 0:none; 1: SVLTE; 2: SRLTE */
  116. {"opt_lte_support", 0},
  117. {"opt_c2k_support", 0},
  118. };
  119. static char *s_g_local_cmd_line_buf;
  120. static int s_g_local_cmd_line_buf_size;
  121. static int s_g_curr_opt_buf_offset;
  122. static int radio_cfg_by_name(void *fdt, int offset, char name[])
  123. {
  124. int len = 0;
  125. const void *fdt_tmp;
  126. fdt_tmp = fdt_getprop(fdt, offset, name, &len);
  127. if (!fdt_tmp || !len)
  128. return -1;
  129. return (int)fdt32_to_cpu(*(unsigned int *)fdt_tmp);
  130. }
  131. static int radio_cap_dts_confirm(void *fdt, int offset, char name[])
  132. {
  133. int len = 0;
  134. const void *fdt_tmp;
  135. fdt_tmp = fdt_getprop(fdt, offset, "compatible", &len);
  136. if (!fdt_tmp || !len)
  137. return -1;
  138. if (strcmp((char*)fdt_tmp, name))
  139. return -1;
  140. return 0;
  141. }
  142. struct radio_md_cap_bit {
  143. char *key;
  144. unsigned int bit;
  145. };
  146. static struct radio_md_cap_bit radio_cap_bitmap_table[] =
  147. {
  148. {"radio_md_g_en", MD_CAP_GSM},
  149. {"radio_md_w_en", MD_CAP_WCDMA},
  150. {"radio_md_t_en", MD_CAP_TDS_CDMA},
  151. {"radio_md_c_en", MD_CAP_CDMA2000},
  152. {"radio_md_lf_en", MD_CAP_FDD_LTE},
  153. {"radio_md_lt_en", MD_CAP_TDD_LTE},
  154. {"radio_md_nr_en", MD_CAP_NR},
  155. };
  156. static int get_radio_cfg_from_dt(void *fdt, unsigned int *radio_cap_bitmap)
  157. {
  158. int nodeoffset;
  159. int ret;
  160. unsigned int i;
  161. if (!radio_cap_bitmap) {
  162. ALWAYS_LOG("cap bitmap is NULL\n");
  163. return -1;
  164. }
  165. nodeoffset = fdt_path_offset(fdt, "/radio_md_cfg");
  166. if (nodeoffset < 0) {
  167. ALWAYS_LOG("/radio_md_cfg disable at dts\n");
  168. return -1;
  169. }
  170. if (radio_cap_dts_confirm(fdt, nodeoffset, "mediatek,radio_md_cfg")) {
  171. ALWAYS_LOG("/radio_md_cfg compatible disable at dts\n");
  172. return -1;
  173. }
  174. for (i = 0; i < sizeof(radio_cap_bitmap_table)/sizeof(struct radio_md_cap_bit); i++) {
  175. ret = radio_cfg_by_name(fdt, nodeoffset, radio_cap_bitmap_table[i].key);
  176. if (ret < 0) {
  177. ALWAYS_LOG("radio cap:%s using default\n", radio_cap_bitmap_table[i].key);
  178. return -1;
  179. }
  180. if (ret > 0)
  181. *radio_cap_bitmap |= radio_cap_bitmap_table[i].bit;
  182. }
  183. ret = radio_cfg_by_name(fdt, nodeoffset, "radio_md_c2k_lte_mode");
  184. if (ret >= 0) {
  185. for (i = 0; i < sizeof(default_option_list)/sizeof(struct opt_cfg); i++) {
  186. if (!strcmp(default_option_list[i].name, "opt_c2k_lte_mode")) {
  187. ALWAYS_LOG("c2k_lte_mode at dts val:%d\n", ret);
  188. default_option_list[i].val = ret;
  189. }
  190. }
  191. }
  192. return 0;
  193. }
  194. /**************************************************************************************************/
  195. /* Local function for telephony */
  196. /**************************************************************************************************/
  197. static unsigned int get_capability_bit(char cap_str[])
  198. {
  199. if (cap_str == NULL)
  200. return 0;
  201. if ((strcmp(cap_str, "LF") == 0) || (strcmp(cap_str, "Lf") == 0) || (strcmp(cap_str, "lf") == 0))
  202. return MD_CAP_FDD_LTE;
  203. if ((strcmp(cap_str, "LT") == 0) || (strcmp(cap_str, "Lt") == 0) || (strcmp(cap_str, "lt") == 0))
  204. return MD_CAP_TDD_LTE;
  205. if ((strcmp(cap_str, "W") == 0) || (strcmp(cap_str, "w") == 0))
  206. return MD_CAP_WCDMA;
  207. if ((strcmp(cap_str, "C") == 0) || (strcmp(cap_str, "c") == 0))
  208. return MD_CAP_CDMA2000;
  209. if ((strcmp(cap_str, "T") == 0) || (strcmp(cap_str, "t") == 0))
  210. return MD_CAP_TDS_CDMA;
  211. if ((strcmp(cap_str, "G") == 0) || (strcmp(cap_str, "g") == 0))
  212. return MD_CAP_GSM;
  213. return 0;
  214. }
  215. #define MAX_CAP_STR_LENGTH 16
  216. static unsigned int get_capablity_bit_map(char str[])
  217. {
  218. char tmp_str[MAX_CAP_STR_LENGTH];
  219. int tmp_str_curr_pos = 0;
  220. unsigned int capability_bit_map = 0;
  221. int str_len;
  222. int i;
  223. if (str == NULL)
  224. return 0;
  225. str_len = strlen(str);
  226. for (i = 0; i < str_len; i++) {
  227. if (str[i] == ' ')
  228. continue;
  229. if (str[i] == '\t')
  230. continue;
  231. if ((str[i] == '/') || (str[i] == '_')) {
  232. if (tmp_str_curr_pos) {
  233. tmp_str[tmp_str_curr_pos] = 0;
  234. capability_bit_map |= get_capability_bit(tmp_str);
  235. }
  236. tmp_str_curr_pos = 0;
  237. continue;
  238. }
  239. if (tmp_str_curr_pos < (MAX_CAP_STR_LENGTH-1)) {
  240. tmp_str[tmp_str_curr_pos] = str[i];
  241. tmp_str_curr_pos++;
  242. } else
  243. break;
  244. }
  245. if (tmp_str_curr_pos) {
  246. tmp_str[tmp_str_curr_pos] = 0;
  247. capability_bit_map |= get_capability_bit(tmp_str);
  248. }
  249. return capability_bit_map;
  250. }
  251. static unsigned int compatible_convert(unsigned int src_rat)
  252. {
  253. unsigned int i;
  254. for (i = 0; i < (sizeof(ubin_convert_table_src)/sizeof(unsigned int)); i++) {
  255. if (ubin_convert_table_src[i] == src_rat)
  256. return ubin_convert_table_des[i];
  257. }
  258. return src_rat;
  259. }
  260. static unsigned int get_ubin_val_by_bitmap(unsigned int rat_bitmap)
  261. {
  262. unsigned int val;
  263. unsigned int i;
  264. val = rat_bitmap & MD_CAP_MASK;
  265. val = compatible_convert(val);
  266. for (i = 0; i < (sizeof(legacy_ubin_rat_map)/sizeof(unsigned int)); i++) {
  267. if (val == legacy_ubin_rat_map[i])
  268. return LEGACY_UBIN_START_ID + i;
  269. }
  270. return rat_bitmap|MD_CAP_KEY;
  271. }
  272. static int cal_md3_type_by_rat_bitmap(unsigned int rat_bitmap)
  273. {
  274. int rat_ver;
  275. long long plat_ret;
  276. plat_ret = ccci_hal_get_ld_md_plat_setting("rat_plat_ver");
  277. if (plat_ret > 0)
  278. rat_ver = (int)plat_ret;
  279. else
  280. rat_ver = RAT_VER_DEFAULT;
  281. switch (rat_ver) {
  282. case RAT_VER_93:
  283. return 0;
  284. case RAT_VER_DEFAULT:
  285. /* go through */
  286. default: /* Include case 0, using univeral bin rat version */
  287. if (rat_bitmap & MD_CAP_CDMA2000)
  288. return md_type_3g;
  289. return 0;
  290. }
  291. }
  292. static int cal_md1_type_by_rat_bitmap(unsigned int rat_bitmap)
  293. {
  294. int rat_ver;
  295. long long plat_ret;
  296. plat_ret = ccci_hal_get_ld_md_plat_setting("rat_plat_ver");
  297. if (plat_ret > 0)
  298. rat_ver = (int)plat_ret;
  299. else
  300. rat_ver = RAT_VER_DEFAULT;
  301. switch (rat_ver) {
  302. case RAT_VER_R8:
  303. if (rat_bitmap & MD_CAP_WCDMA)
  304. return md_type_wg;
  305. if (rat_bitmap & MD_CAP_TDS_CDMA)
  306. return md_type_tg;
  307. if (rat_bitmap & MD_CAP_GSM)
  308. return md_type_2g;
  309. return 0;
  310. case RAT_VER_90:
  311. /* 5, 6, 3, 4, 1 */
  312. if (rat_bitmap & (MD_CAP_FDD_LTE | MD_CAP_TDD_LTE)) {
  313. if ((rat_bitmap & (MD_CAP_TDS_CDMA | MD_CAP_WCDMA)) == (MD_CAP_TDS_CDMA | MD_CAP_WCDMA))
  314. return md_type_ltg;
  315. if (rat_bitmap & MD_CAP_TDS_CDMA)
  316. return md_type_ltg;
  317. if (rat_bitmap & MD_CAP_WCDMA)
  318. return md_type_lwg;
  319. return md_type_lwg; /* Using lwg as default */
  320. }
  321. if ((rat_bitmap & MD_CAP_MASK) == (MD_CAP_WCDMA | MD_CAP_GSM | MD_CAP_CDMA2000))
  322. return md_type_lwg; /* Special setting for wcg with non-lk load modem */
  323. if (rat_bitmap & MD_CAP_WCDMA)
  324. return md_type_wg;
  325. if (rat_bitmap & MD_CAP_TDS_CDMA)
  326. return md_type_tg;
  327. if (rat_bitmap & MD_CAP_GSM)
  328. return md_type_2g;
  329. return 0;
  330. case RAT_VER_DEFAULT:
  331. /* go through */
  332. default: /* Include case 0, using univeral bin rat version */
  333. return (int)get_ubin_val_by_bitmap(rat_bitmap);
  334. }
  335. }
  336. static int append_rat_str(char buf[], int size, char append_str[])
  337. {
  338. int buf_used;
  339. int append_size;
  340. int left_size;
  341. buf_used = strlen(buf);
  342. append_size = strlen(append_str) + 1;
  343. left_size = size - buf_used;
  344. if (left_size > append_size) {
  345. if (buf_used > 0)
  346. return snprintf(&buf[buf_used], left_size, "/%s", append_str);
  347. return snprintf(&buf[buf_used], left_size, "%s", append_str);
  348. }
  349. return -1;
  350. }
  351. static void rat_bitmap_to_str(unsigned int rat_bitmap, char rat_str_des[], int des_size)
  352. {
  353. if (des_size > 0) {
  354. rat_str_des[des_size - 1] = 0;
  355. if (rat_bitmap == 0) {
  356. rat_str_des[0] = 0;
  357. return;
  358. }
  359. } else
  360. return;
  361. /* Gen string */
  362. if (rat_bitmap & MD_CAP_CDMA2000)
  363. append_rat_str(rat_str_des, des_size, "C");
  364. if (rat_bitmap & MD_CAP_FDD_LTE)
  365. append_rat_str(rat_str_des, des_size, "Lf");
  366. if (rat_bitmap & MD_CAP_TDD_LTE)
  367. append_rat_str(rat_str_des, des_size, "Lt");
  368. if (rat_bitmap & MD_CAP_WCDMA)
  369. append_rat_str(rat_str_des, des_size, "W");
  370. if (rat_bitmap & MD_CAP_TDS_CDMA)
  371. append_rat_str(rat_str_des, des_size, "T");
  372. if (rat_bitmap & MD_CAP_GSM)
  373. append_rat_str(rat_str_des, des_size, "G");
  374. }
  375. static int get_md_support_value_by_rat_bitmap(int md_id, unsigned int rat_bitmap)
  376. {
  377. if (md_id == MD_SYS1)
  378. return cal_md1_type_by_rat_bitmap(rat_bitmap);
  379. if (md_id == MD_SYS3)
  380. return cal_md3_type_by_rat_bitmap(rat_bitmap);
  381. return 0;
  382. }
  383. static void adjust_setting_by_rat_bitmap(unsigned int bit_map, struct opt_cfg option_list[], int num)
  384. {
  385. int i;
  386. for (i = 0; i < num; i++) {
  387. if (strcmp(option_list[i].name, "opt_md1_support") == 0) {
  388. #ifdef DUMMY_AP_MODE
  389. option_list[i].val = 12;
  390. #else
  391. option_list[i].val = get_md_support_value_by_rat_bitmap(MD_SYS1, bit_map);
  392. #endif
  393. continue;
  394. }
  395. if (strcmp(option_list[i].name, "opt_md3_support") == 0) {
  396. #ifdef DUMMY_AP_MODE
  397. option_list[i].val = 2;
  398. #else
  399. option_list[i].val = get_md_support_value_by_rat_bitmap(MD_SYS3, bit_map);
  400. #endif
  401. continue;
  402. }
  403. if (strcmp(option_list[i].name, "opt_c2k_support") == 0) {
  404. if (bit_map & MD_CAP_CDMA2000)
  405. option_list[i].val = 1;
  406. else
  407. option_list[i].val = 0;
  408. continue;
  409. }
  410. if (strcmp(option_list[i].name, "opt_lte_support") == 0) {
  411. if (bit_map & (MD_CAP_FDD_LTE | MD_CAP_TDD_LTE))
  412. option_list[i].val = 1;
  413. else
  414. option_list[i].val = 0;
  415. continue;
  416. }
  417. }
  418. }
  419. static int option_validation_check(unsigned int bit_map, struct opt_cfg option_list[], int num)
  420. {
  421. int i;
  422. int md1_support = 0, md3_support = 0, lte_support = 0;
  423. int val;
  424. for (i = 0; i < num; i++) {
  425. if (strcmp(option_list[i].name, "opt_md1_support") == 0) {
  426. md1_support = option_list[i].val;
  427. continue;
  428. }
  429. if (strcmp(option_list[i].name, "opt_md3_support") == 0) {
  430. md3_support = option_list[i].val;
  431. continue;
  432. }
  433. if (strcmp(option_list[i].name, "opt_lte_support") == 0) {
  434. lte_support = option_list[i].val;
  435. continue;
  436. }
  437. }
  438. /* Check lte_support */
  439. if ((!!(bit_map & (MD_CAP_FDD_LTE | MD_CAP_TDD_LTE))) != (!!lte_support))
  440. return -1;
  441. /* Check opt_md1_support */
  442. val = get_md_support_value_by_rat_bitmap(MD_SYS1, bit_map);
  443. if ((val > 0) && (md1_support == 0))
  444. return -1;
  445. if ((val == 0) && (md1_support > 0))
  446. return -1;
  447. /* Check opt_md3_support */
  448. val = get_md_support_value_by_rat_bitmap(MD_SYS3, bit_map);
  449. if ((val > 0) && (md3_support == 0))
  450. return -1;
  451. if ((val == 0) && (md3_support > 0))
  452. return -1;
  453. /* All check OK */
  454. return 0;
  455. }
  456. /* Using command line buffer to store opt value */
  457. static int add_opt_setting_to_buf(char name[], char val[])
  458. {
  459. int name_len;
  460. int value_len;
  461. if ((name == NULL) || (val == NULL)) {
  462. ALWAYS_LOG("dt args invalid\n");
  463. return -1;
  464. }
  465. name_len = strlen(name) + 1;
  466. value_len = strlen(val) + 1;
  467. if ((s_g_local_cmd_line_buf_size - s_g_curr_opt_buf_offset) < (value_len + name_len)) {
  468. ALWAYS_LOG("dt buf free size not enough\n");
  469. return -1;
  470. }
  471. /* copy name */
  472. memcpy(&s_g_local_cmd_line_buf[s_g_curr_opt_buf_offset], name, name_len);
  473. s_g_curr_opt_buf_offset += name_len;
  474. /* copy value */
  475. memcpy(&s_g_local_cmd_line_buf[s_g_curr_opt_buf_offset], val, value_len);
  476. s_g_curr_opt_buf_offset += value_len;
  477. return 0;
  478. }
  479. struct tel_mode_case {
  480. char *ps1_rat;
  481. int md1_support;
  482. int md3_support;
  483. int c2k_lte_mode;
  484. };
  485. struct tel_mode_case tel_mode_list[] = {
  486. {.ps1_rat = "C/W/G", .md1_support = 11, .md3_support = 0, .c2k_lte_mode = 2,}, /* C2K 3M (C/W/G) */
  487. {.ps1_rat = "Lf/W/G", .md1_support = 14, .md3_support = 0, .c2k_lte_mode = 0,}, /* FDD 3M (Lf/W/G) */
  488. {.ps1_rat = "Lt/T/G", .md1_support = 13, .md3_support = 0, .c2k_lte_mode = 0,}, /* TDD 3M (Lt/T/G) */
  489. {.ps1_rat = "C/Lf/Lt/G", .md1_support = 11, .md3_support = 0, .c2k_lte_mode = 2,}, /* C2K 4M (C/Lf/Lt/G) */
  490. {.ps1_rat = "Lf/Lt/W/G", .md1_support = 9, .md3_support = 0, .c2k_lte_mode = 0,}, /* FDD 4M (Lf/Lt/W/G) */
  491. {.ps1_rat = "C/Lf/Lt/W/G", .md1_support = 11, .md3_support = 0, .c2k_lte_mode = 2,}, /* C2K 5M (C/Lf/Lt/W/G) */
  492. {.ps1_rat = "Lf/Lt/W/T/G", .md1_support = 10, .md3_support = 0, .c2k_lte_mode = 0,}, /* FDD 5M (Lf/Lt/W/T/G) */
  493. {.ps1_rat = "C/Lf/Lt/W/T/G", .md1_support = 12, .md3_support = 0, .c2k_lte_mode = 2,} /* 6M (C/Lf/Lt/W/T/G) */
  494. };
  495. static int cust_tel_mode_calc_by_idx(int idx, struct opt_cfg *d_opt_list, int num, unsigned int *cap_bit_map)
  496. {
  497. int i;
  498. if (idx >= (int)(sizeof(tel_mode_list)/sizeof(struct tel_mode_case)))
  499. return -1;
  500. *cap_bit_map = get_capablity_bit_map(tel_mode_list[idx].ps1_rat);
  501. for (i = 0; i < num; i++) {
  502. if (strcmp(d_opt_list[i].name, "opt_md1_support") == 0) {
  503. d_opt_list[i].val = tel_mode_list[idx].md1_support;
  504. continue;
  505. }
  506. if (strcmp(d_opt_list[i].name, "opt_md3_support") == 0) {
  507. d_opt_list[i].val = tel_mode_list[idx].md3_support;
  508. continue;
  509. }
  510. if (strcmp(d_opt_list[i].name, "opt_c2k_lte_mode") == 0) {
  511. d_opt_list[i].val = tel_mode_list[idx].c2k_lte_mode;
  512. continue;
  513. }
  514. }
  515. return 0;
  516. }
  517. static void update_to_default(struct opt_cfg *d_opt_list, struct opt_cfg *default_list, int num)
  518. {
  519. int i, j;
  520. for (i = 0; i < num; i++) {
  521. if (strcmp(d_opt_list[i].name, default_list[i].name) == 0) {
  522. default_list[i].val = d_opt_list[i].val;
  523. continue;
  524. }
  525. for (j = 0; j < num; j++) {
  526. if (strcmp(d_opt_list[j].name, default_list[i].name) == 0) {
  527. default_list[i].val = d_opt_list[j].val;
  528. break;
  529. }
  530. }
  531. }
  532. }
  533. static int mtk_tel_mode_calc(struct opt_cfg *d_opt_list, int num, unsigned int *cap_bit_map)
  534. {
  535. int i;
  536. char *ret_val_ptr;
  537. int val;
  538. int has_update = 0;
  539. ret_val_ptr = get_lk_ro_env_str("opt_ps1_rat");
  540. *cap_bit_map = get_capablity_bit_map(ret_val_ptr);
  541. if (ret_val_ptr)
  542. has_update = 1;
  543. for (i = 0; i < num; i++) {
  544. ret_val_ptr = get_lk_ro_env_str(d_opt_list[i].name);
  545. if (ret_val_ptr) {
  546. has_update = 1;
  547. val = str2uint(ret_val_ptr);
  548. d_opt_list[i].val = val;
  549. }
  550. }
  551. if (has_update)
  552. return 0;
  553. return -1;
  554. }
  555. int dynamic_setting_calc(struct opt_cfg *d_opt_list, unsigned int *cap_bit_map)
  556. {
  557. int idx, ret;
  558. unsigned int cfg_item_num = sizeof(default_option_list)/sizeof(struct opt_cfg);
  559. /* Copy default setting */
  560. memcpy(d_opt_list, default_option_list, sizeof(default_option_list));
  561. /* Check custom telephony switch setting */
  562. idx = get_cust_tel_mode_idx();
  563. ALWAYS_LOG("cust_tel_mode_idx val:%d\n", idx);
  564. if (idx >= 0) /* Using custom setting */
  565. ret = cust_tel_mode_calc_by_idx(idx, d_opt_list, (int)cfg_item_num, cap_bit_map);
  566. else /* Using mtk solution */
  567. ret = mtk_tel_mode_calc(d_opt_list, (int)cfg_item_num, cap_bit_map);
  568. if (ret < 0)
  569. return 1;/* No change */
  570. adjust_setting_by_rat_bitmap(*cap_bit_map, d_opt_list, cfg_item_num);
  571. ret = option_validation_check(*cap_bit_map, d_opt_list, cfg_item_num);
  572. if (ret == 0)
  573. return 0; /* Changed */
  574. else
  575. return -1;/* Roll back to default */
  576. }
  577. /***********************************************************************************************/
  578. /* Functions that will be called by exteranl */
  579. /***********************************************************************************************/
  580. int update_md_opt_to_fdt_firmware(void *fdt)
  581. {
  582. #ifdef LK_OPT_TO_KERNEL_CCCI
  583. int nodeoffset;
  584. char *name, *value;
  585. int name_len, val_len;
  586. int i = 0;
  587. if (s_g_curr_opt_buf_offset == 0) {
  588. ALWAYS_LOG("no need update md_opt_cfg\n");
  589. return 0;
  590. }
  591. nodeoffset = fdt_path_offset(fdt, "/firmware/android");
  592. if (nodeoffset < 0) {
  593. ALWAYS_LOG("/firmware/android not found\n");
  594. return -1;
  595. }
  596. while (i < s_g_curr_opt_buf_offset) {
  597. name_len = strlen(&s_g_local_cmd_line_buf[i]) + 1;
  598. name = &s_g_local_cmd_line_buf[i];
  599. i += name_len;
  600. val_len = strlen(&s_g_local_cmd_line_buf[i]) + 1;
  601. value = &s_g_local_cmd_line_buf[i];
  602. i += val_len;
  603. fdt_setprop_string(fdt, nodeoffset, name, value);
  604. }
  605. #endif
  606. return 0;
  607. }
  608. int prepare_tel_fo_setting(void)
  609. {
  610. #ifndef LK_NO_SUPPORT_MD_CCCI
  611. unsigned int i;
  612. char val_str[8];
  613. char *new_value = NULL;
  614. char def_rat_str[32];
  615. int value;
  616. struct opt_cfg *new_opt_list;
  617. int using_default = 1; /* 1: Using default, 0: Using new setting, -1: New setting abnormal */
  618. unsigned int default_cap_bit_map, cap_bit_map = 0, dts_cap_bitmap;
  619. unsigned int cfg_item_num = sizeof(default_option_list)/sizeof(struct opt_cfg);
  620. int ret;
  621. /* Prepare default option setting */
  622. dts_cap_bitmap = 0;
  623. if (get_radio_cfg_from_dt(get_kernel_fdt(), &dts_cap_bitmap) < 0)
  624. default_cap_bit_map = get_capablity_bit_map(PS1_RAT_DEFAULT);
  625. else
  626. default_cap_bit_map = dts_cap_bitmap;
  627. if (default_cap_bit_map)
  628. adjust_setting_by_rat_bitmap(default_cap_bit_map, default_option_list, cfg_item_num);
  629. /* Prepare dynamic env setting table */
  630. new_opt_list = (struct opt_cfg *)malloc(sizeof(default_option_list));
  631. if (new_opt_list)
  632. using_default = dynamic_setting_calc(new_opt_list, &cap_bit_map);
  633. if (using_default == 0) {
  634. update_to_default(new_opt_list, default_option_list, (int)cfg_item_num);
  635. default_cap_bit_map = cap_bit_map;
  636. }
  637. /* Update to tag buffer for kernel */
  638. for (i = 0; i < cfg_item_num; i++) {
  639. snprintf(val_str, sizeof(val_str), "%d", default_option_list[i].val);
  640. add_opt_setting_to_buf(default_option_list[i].name, val_str);
  641. ret = insert_ccci_tag_inf(default_option_list[i].name,
  642. (char*)&default_option_list[i].val, sizeof(int));
  643. if(ret < 0)
  644. ALWAYS_LOG("insert %s fail\n", default_option_list[i].name);
  645. }
  646. def_rat_str[0] = '\0';
  647. if (default_cap_bit_map) {
  648. rat_bitmap_to_str(default_cap_bit_map, def_rat_str, sizeof(def_rat_str));
  649. add_opt_setting_to_buf("opt_ps1_rat", def_rat_str);
  650. ret = insert_ccci_tag_inf("opt_ps1_rat",
  651. (char*)&default_cap_bit_map, sizeof(int));
  652. if(ret < 0)
  653. ALWAYS_LOG("insert opt_ps1_rat fail\n");
  654. }
  655. ALWAYS_LOG("Radio cap final:%s[0x%x]\n", def_rat_str, default_cap_bit_map);
  656. def_rat_str[0] = '\0';
  657. rat_bitmap_to_str(dts_cap_bitmap, def_rat_str, sizeof(def_rat_str));
  658. ALWAYS_LOG(" ----- dts:%s[0x%x]\n", def_rat_str, dts_cap_bitmap);
  659. def_rat_str[0] = '\0';
  660. rat_bitmap_to_str(get_capablity_bit_map(PS1_RAT_DEFAULT), def_rat_str, sizeof(def_rat_str));
  661. ALWAYS_LOG(" ----- prj:%s[0x%x]\n", def_rat_str, get_capablity_bit_map(PS1_RAT_DEFAULT));
  662. def_rat_str[0] = '\0';
  663. rat_bitmap_to_str(cap_bit_map, def_rat_str, sizeof(def_rat_str));
  664. ALWAYS_LOG(" --dynamic:%s[0x%x]\n", def_rat_str, cap_bit_map);
  665. /* update using default or not */
  666. ret = insert_ccci_tag_inf("opt_using_default",
  667. (char*)&using_default, sizeof(int));
  668. if(ret < 0)
  669. ALWAYS_LOG("insert opt_using_default fail\n");
  670. snprintf(val_str, sizeof(val_str), "%d", using_default);
  671. add_opt_setting_to_buf("opt_using_default", val_str);
  672. /* update platform option */
  673. value = (int)ccci_hal_get_ld_md_plat_setting("rat_plat_ver");
  674. if ((value == RAT_VER_R8) || (value == RAT_VER_90))
  675. value = 0;
  676. else if (value == RAT_VER_91_92)
  677. value = 1;
  678. else if (value == RAT_VER_93)
  679. value = 1;
  680. else
  681. value = 1;
  682. snprintf(val_str, sizeof(val_str), "%d", value);
  683. add_opt_setting_to_buf("opt_eccci_c2k", val_str);
  684. ret = insert_ccci_tag_inf("opt_eccci_c2k", (char*)&value, sizeof(int));
  685. if(ret < 0)
  686. ALWAYS_LOG("insert opt_eccci_c2k fail\n");
  687. new_value = get_env("msim_config");
  688. if (new_value != NULL)
  689. add_opt_setting_to_buf("product.hardware.sku", new_value);
  690. /* Notify Kernel using LK setting */
  691. #ifdef LK_OPT_TO_KERNEL_CCCI
  692. value = 1;
  693. ret = insert_ccci_tag_inf("opt_using_lk_val",
  694. (char*)&value, sizeof(int)); /* Notify Kernel using kernel setting */
  695. if(ret < 0)
  696. ALWAYS_LOG("insert opt_using_lk_val fail\n");
  697. #endif
  698. if (new_opt_list)
  699. free(new_opt_list);
  700. #endif
  701. return 0;
  702. }
  703. int ccci_get_opt_val(char opt[])
  704. {
  705. int i;
  706. for (i = 0; i < (int)(sizeof(default_option_list)/sizeof(struct opt_cfg)); i++) {
  707. if (strcmp(default_option_list[i].name, opt) == 0) {
  708. return default_option_list[i].val;
  709. }
  710. }
  711. return -LD_ERR_OPT_NOT_FOUND;
  712. }
  713. int ccci_alloc_local_cmd_line_buf(int size)
  714. {
  715. s_g_local_cmd_line_buf = malloc(size);
  716. if (s_g_local_cmd_line_buf == NULL)
  717. return -LD_ERR_OPT_CMD_BUF_ALLOC_FAIL;
  718. s_g_local_cmd_line_buf_size = size;
  719. return 0;
  720. }
  721. void ccci_free_local_cmd_line_buf(void)
  722. {
  723. if (s_g_local_cmd_line_buf)
  724. free(s_g_local_cmd_line_buf);
  725. s_g_local_cmd_line_buf_size = 0;
  726. }
  727. int ccci_ld_md_tel_init(void)
  728. {
  729. if (ccci_alloc_local_cmd_line_buf(1024) < 0) {
  730. ALWAYS_LOG("allocate local cmd line memory fail\n");
  731. return -1;
  732. }
  733. prepare_tel_fo_setting();
  734. return 0;
  735. }