fm_config.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. #include <linux/string.h>
  2. #include <linux/slab.h>
  3. #include "fm_typedef.h"
  4. #include "fm_rds.h"
  5. #include "fm_dbg.h"
  6. #include "fm_err.h"
  7. #include "fm_stdlib.h"
  8. #include "fm_patch.h"
  9. #include "fm_config.h"
  10. #if (!defined(MT6628_FM) && !defined(MT6620_FM) && !defined(MT6627_FM) && !defined(MT6580_FM) && !defined(MT6630_FM))
  11. #include "fm_cust_cfg.h"
  12. #endif
  13. static fm_cust_cfg fm_config;
  14. static fm_s32 fm_index;
  15. #if 0
  16. static fm_s32 to_upper(fm_s8 *str)
  17. {
  18. fm_s32 i = 0;
  19. for (i = 0; i < (int)strlen(str); i++) {
  20. if (('a' <= str[i]) && (str[i] <= 'z'))
  21. str[i] = str[i] - ('a' - 'A');
  22. }
  23. return 0;
  24. }
  25. #endif
  26. fm_s32 to_upper_n(fm_s8 *str, fm_s32 len)
  27. {
  28. fm_s32 i = 0;
  29. for (i = 0; i < len; i++) {
  30. if (('a' <= str[i]) && (str[i] <= 'z'))
  31. str[i] = str[i] - ('a' - 'A');
  32. }
  33. return 0;
  34. }
  35. fm_s32 check_hex_str(fm_s8 *str, fm_s32 len)
  36. {
  37. fm_s32 i = 0;
  38. for (i = 0; i < len; i++) {
  39. if ((('a' <= str[i]) && (str[i] <= 'z')) || (('A' <= str[i]) && (str[i] <= 'Z'))
  40. || (('0' <= str[i]) && (str[i] <= '9'))) {
  41. ;
  42. } else {
  43. return -1;
  44. }
  45. }
  46. return 0;
  47. }
  48. fm_s32 check_dec_str(fm_s8 *str, fm_s32 len)
  49. {
  50. fm_s32 i = 0;
  51. for (i = 0; i < len; i++) {
  52. if (('0' <= str[i]) && (str[i] <= '9'))
  53. ;
  54. else
  55. return -1;
  56. }
  57. return 0;
  58. }
  59. fm_s32 ascii_to_hex(fm_s8 *in_ascii, fm_u16 *out_hex)
  60. {
  61. fm_s32 len = (fm_s32) strlen(in_ascii);
  62. int i = 0;
  63. fm_u16 tmp;
  64. len = (len > 4) ? 4 : len;
  65. if (check_hex_str(in_ascii, len))
  66. return -1;
  67. to_upper_n(in_ascii, len);
  68. *out_hex = 0;
  69. for (i = 0; i < len; i++) {
  70. if (in_ascii[len - i - 1] < 'A') {
  71. tmp = in_ascii[len - i - 1];
  72. *out_hex |= ((tmp - '0') << (4 * i));
  73. } else {
  74. tmp = in_ascii[len - i - 1];
  75. *out_hex |= ((tmp - 'A' + 10) << (4 * i));
  76. }
  77. }
  78. return 0;
  79. }
  80. fm_s32 ascii_to_dec(fm_s8 *in_ascii, fm_s32 *out_dec)
  81. {
  82. fm_s32 len = (fm_s32) strlen(in_ascii);
  83. int i = 0;
  84. int flag;
  85. int multi = 1;
  86. len = (len > 10) ? 10 : len;
  87. if (in_ascii[0] == '-') {
  88. flag = -1;
  89. in_ascii += 1;
  90. len -= 1;
  91. } else {
  92. flag = 1;
  93. }
  94. if (check_dec_str(in_ascii, len))
  95. return -1;
  96. *out_dec = 0;
  97. multi = 1;
  98. for (i = 0; i < len; i++) {
  99. *out_dec += ((in_ascii[len - i - 1] - '0') * multi);
  100. multi *= 10;
  101. }
  102. *out_dec *= flag;
  103. return 0;
  104. }
  105. fm_s32 trim_string(fm_s8 **start)
  106. {
  107. fm_s8 *end = *start;
  108. /* Advance to non-space character */
  109. while (*(*start) == ' ')
  110. (*start)++;
  111. /* Move to end of string */
  112. while (*end != '\0')
  113. (end)++;
  114. /* Backup to non-space character */
  115. do {
  116. end--;
  117. } while ((end >= *start) && (*end == ' '));
  118. /* Terminate string after last non-space character */
  119. *(++end) = '\0';
  120. return end - *start;
  121. }
  122. fm_s32 trim_path(fm_s8 **start)
  123. {
  124. fm_s8 *end = *start;
  125. while (*(*start) == ' ')
  126. (*start)++;
  127. while (*end != '\0')
  128. (end)++;
  129. do {
  130. end--;
  131. } while ((end >= *start) && ((*end == ' ') || (*end == '\n') || (*end == '\r')));
  132. *(++end) = '\0';
  133. return end - *start;
  134. }
  135. fm_s32 cfg_parser(fm_s8 *buffer, CFG_HANDLER handler, fm_cust_cfg *cfg)
  136. {
  137. fm_s32 ret = 0;
  138. fm_s8 *p = buffer;
  139. fm_s8 *group_start = NULL;
  140. fm_s8 *key_start = NULL;
  141. fm_s8 *value_start = NULL;
  142. enum fm_cfg_parser_state state = FM_CFG_STAT_NONE;
  143. if (p == NULL) {
  144. pr_err("%s,invalid pointer\n", __func__);
  145. return -FM_EPARA;
  146. }
  147. for (p = buffer; *p != '\0'; p++) {
  148. switch (state) {
  149. case FM_CFG_STAT_NONE:{
  150. if (*p == '[') {
  151. /* if we get char '[' in none state, it means a new group name start */
  152. state = FM_CFG_STAT_GROUP;
  153. group_start = p + 1;
  154. } else if (*p == COMMENT_CHAR) {
  155. /* if we get char '#' in none state, it means a new comment start */
  156. state = FM_CFG_STAT_COMMENT;
  157. } else if (!isspace(*p) && (*p != '\n') && (*p != '\r')) {
  158. /* if we get an nonspace char in none state, it means a new key start */
  159. state = FM_CFG_STAT_KEY;
  160. key_start = p;
  161. }
  162. break;
  163. }
  164. case FM_CFG_STAT_GROUP:{
  165. if (*p == ']') {
  166. /* if we get char ']' in group state, it means a group name complete */
  167. *p = '\0';
  168. /* FIX_ME */
  169. /* record group name */
  170. state = FM_CFG_STAT_NONE;
  171. trim_string(&group_start);
  172. /* WCN_DBG(FM_NTC|MAIN, "g=%s\n", group_start); */
  173. }
  174. break;
  175. }
  176. case FM_CFG_STAT_COMMENT:{
  177. if (*p == '\n') {
  178. /* if we get char '\n' in comment state, it means new line start */
  179. state = FM_CFG_STAT_NONE;
  180. group_start = p + 1;
  181. }
  182. break;
  183. }
  184. case FM_CFG_STAT_KEY:{
  185. if (*p == DELIMIT_CHAR) {
  186. /* if we get char '=' in key state, it means a key name complete */
  187. *p = '\0';
  188. /* FIX_ME */
  189. /* record key name */
  190. state = FM_CFG_STAT_VALUE;
  191. value_start = p + 1;
  192. trim_string(&key_start);
  193. /* WCN_DBG(FM_NTC|MAIN, "k=%s\n", key_start); */
  194. }
  195. break;
  196. }
  197. case FM_CFG_STAT_VALUE:{
  198. if (*p == '\n' || *p == '\r') {
  199. /* if we get char '\n' or '\r' in value state, it means a value complete */
  200. *p = '\0';
  201. /* record value */
  202. trim_string(&value_start);
  203. /* WCN_DBG(FM_NTC|MAIN, "v=%s\n", value_start); */
  204. if (handler)
  205. ret = handler(group_start, key_start, value_start, cfg);
  206. state = FM_CFG_STAT_NONE;
  207. }
  208. break;
  209. }
  210. default:
  211. break;
  212. }
  213. }
  214. return ret;
  215. }
  216. fm_s32 cfg_item_match(fm_s8 *src_key, fm_s8 *src_val, fm_s8 *dst_key, fm_s32 *dst_val)
  217. {
  218. fm_s32 ret = 0;
  219. fm_u16 tmp_hex;
  220. fm_s32 tmp_dec;
  221. /* WCN_DBG(FM_NTC|MAIN,"src_key=%s,src_val=%s\n", src_key,src_val); */
  222. /* WCN_DBG(FM_NTC|MAIN,"dst_key=%s\n", dst_key); */
  223. if (strcmp(src_key, dst_key) == 0) {
  224. if (strncmp(src_val, "0x", strlen("0x")) == 0) {
  225. src_val += strlen("0x");
  226. /* WCN_DBG(FM_NTC|MAIN,"%s\n", src_val); */
  227. ret = ascii_to_hex(src_val, &tmp_hex);
  228. if (!ret) {
  229. *dst_val = tmp_hex;
  230. /* WCN_DBG(FM_NTC|MAIN, "%s 0x%04x\n", dst_key, tmp_hex); */
  231. return 0;
  232. }
  233. /* WCN_DBG(FM_ERR | MAIN, "%s format error\n", dst_key); */
  234. return 1;
  235. }
  236. ret = ascii_to_dec(src_val, &tmp_dec);
  237. if (!ret /*&& ((0 <= tmp_dec) && (tmp_dec <= 0xFFFF)) */) {
  238. *dst_val = tmp_dec;
  239. /* WCN_DBG(FM_NTC|MAIN, "%s %d\n", dst_key, tmp_dec); */
  240. return 0;
  241. }
  242. /* WCN_DBG(FM_ERR | MAIN, "%s format error\n", dst_key); */
  243. return 1;
  244. }
  245. /* else */
  246. /* { */
  247. /* WCN_DBG(FM_ERR | MAIN, "src_key!=dst_key\n"); */
  248. /* } */
  249. return -1;
  250. }
  251. static fm_s32 cfg_item_handler(fm_s8 *grp, fm_s8 *key, fm_s8 *val, fm_cust_cfg *cfg)
  252. {
  253. fm_s32 ret = 0;
  254. struct fm_rx_cust_cfg *rx_cfg = &cfg->rx_cfg;
  255. struct fm_tx_cust_cfg *tx_cfg = &cfg->tx_cfg;
  256. ret = cfg_item_match(key, val, "FMR_RSSI_TH_L", &rx_cfg->long_ana_rssi_th);
  257. if (0 <= ret)
  258. return ret;
  259. ret = cfg_item_match(key, val, "FMR_RSSI_TH_S", &rx_cfg->short_ana_rssi_th);
  260. if (0 <= ret)
  261. return ret;
  262. ret = cfg_item_match(key, val, "FMR_CQI_TH", &rx_cfg->cqi_th);
  263. if (0 <= ret)
  264. return ret;
  265. ret = cfg_item_match(key, val, "FMR_MR_TH", &rx_cfg->mr_th);
  266. if (0 <= ret)
  267. return ret;
  268. ret = cfg_item_match(key, val, "FMR_SMG_TH", &rx_cfg->smg_th);
  269. if (0 <= ret)
  270. return ret;
  271. ret = cfg_item_match(key, val, "FMR_SCAN_CH_SIZE", &rx_cfg->scan_ch_size);
  272. if (0 <= ret)
  273. return ret;
  274. ret = cfg_item_match(key, val, "FMR_SCAN_SORT", &rx_cfg->scan_sort);
  275. if (0 <= ret)
  276. return ret;
  277. ret = cfg_item_match(key, val, "FMR_SEEK_SPACE", &rx_cfg->seek_space);
  278. if (0 <= ret)
  279. return ret;
  280. ret = cfg_item_match(key, val, "FMR_BAND", &rx_cfg->band);
  281. if (0 <= ret)
  282. return ret;
  283. ret = cfg_item_match(key, val, "FMR_BAND_FREQ_L", &rx_cfg->band_freq_l);
  284. if (0 <= ret)
  285. return ret;
  286. ret = cfg_item_match(key, val, "FMR_BAND_FREQ_H", &rx_cfg->band_freq_h);
  287. if (0 <= ret)
  288. return ret;
  289. ret = cfg_item_match(key, val, "FMR_FAKE_CH", &rx_cfg->fake_ch[fm_index]);
  290. if (0 <= ret) {
  291. fm_index += 1;
  292. rx_cfg->fake_ch_num = (rx_cfg->fake_ch_num < fm_index) ? fm_index : rx_cfg->fake_ch_num;
  293. return ret;
  294. }
  295. ret = cfg_item_match(key, val, "FMR_FAKE_CH_RSSI", &rx_cfg->fake_ch_rssi_th);
  296. if (0 <= ret)
  297. return ret;
  298. ret = cfg_item_match(key, val, "FMR_DEEMPHASIS", &rx_cfg->deemphasis);
  299. if (0 <= ret)
  300. return ret;
  301. ret = cfg_item_match(key, val, "FMR_OSC_FREQ", &rx_cfg->osc_freq);
  302. if (0 <= ret)
  303. return ret;
  304. ret = cfg_item_match(key, val, "FMT_SCAN_HOLE_L", &tx_cfg->scan_hole_low);
  305. if (0 <= ret)
  306. return ret;
  307. ret = cfg_item_match(key, val, "FMT_SCAN_HOLE_H", &tx_cfg->scan_hole_high);
  308. if (0 <= ret)
  309. return ret;
  310. ret = cfg_item_match(key, val, "FMT_PWR_LVL_MAX", &tx_cfg->power_level);
  311. if (0 <= ret)
  312. return ret;
  313. WCN_DBG(FM_WAR | MAIN, "invalid key\n");
  314. return -1;
  315. }
  316. static fm_s32 fm_cust_config_default(fm_cust_cfg *cfg)
  317. {
  318. if (cfg == NULL) {
  319. pr_err("%s,invalid pointer\n", __func__);
  320. return -FM_EPARA;
  321. }
  322. #if (!defined(MT6628_FM) && !defined(MT6620_FM) && !defined(MT6627_FM) && !defined(MT6580_FM) && !defined(MT6630_FM))
  323. cfg->rx_cfg.long_ana_rssi_th = FM_RX_RSSI_TH_LONG;
  324. cfg->rx_cfg.short_ana_rssi_th = FM_RX_RSSI_TH_SHORT;
  325. cfg->rx_cfg.cqi_th = FM_RX_CQI_TH;
  326. cfg->rx_cfg.mr_th = FM_RX_MR_TH;
  327. cfg->rx_cfg.smg_th = FM_RX_SMG_TH;
  328. cfg->rx_cfg.scan_ch_size = FM_RX_SCAN_CH_SIZE;
  329. cfg->rx_cfg.seek_space = FM_RX_SEEK_SPACE;
  330. cfg->rx_cfg.band = FM_RX_BAND;
  331. cfg->rx_cfg.band_freq_l = FM_RX_BAND_FREQ_L;
  332. cfg->rx_cfg.band_freq_h = FM_RX_BAND_FREQ_H;
  333. cfg->rx_cfg.scan_sort = FM_RX_SCAN_SORT_SELECT;
  334. cfg->rx_cfg.fake_ch_num = FM_RX_FAKE_CH_NUM;
  335. cfg->rx_cfg.fake_ch_rssi_th = FM_RX_FAKE_CH_RSSI;
  336. cfg->rx_cfg.fake_ch[0] = FM_RX_FAKE_CH_1;
  337. cfg->rx_cfg.fake_ch[1] = FM_RX_FAKE_CH_2;
  338. cfg->rx_cfg.fake_ch[2] = FM_RX_FAKE_CH_3;
  339. cfg->rx_cfg.fake_ch[3] = FM_RX_FAKE_CH_4;
  340. cfg->rx_cfg.fake_ch[4] = FM_RX_FAKE_CH_5;
  341. cfg->rx_cfg.deemphasis = FM_RX_DEEMPHASIS;
  342. cfg->tx_cfg.scan_hole_low = FM_TX_SCAN_HOLE_LOW;
  343. cfg->tx_cfg.scan_hole_high = FM_TX_SCAN_HOLE_HIGH;
  344. cfg->tx_cfg.power_level = FM_TX_PWR_LEVEL_MAX;
  345. #endif
  346. return 0;
  347. }
  348. static fm_s32 fm_cust_config_file(const fm_s8 *filename, fm_cust_cfg *cfg)
  349. {
  350. fm_s32 ret = 0;
  351. fm_s8 *buf = NULL;
  352. fm_s32 file_len = 0;
  353. buf = fm_zalloc(4096);
  354. if (!buf) {
  355. WCN_DBG(FM_ALT | MAIN, "-ENOMEM\n");
  356. return -ENOMEM;
  357. }
  358. fm_index = 0;
  359. file_len = fm_file_read(filename, buf, 4096, 0);
  360. if (file_len <= 0) {
  361. ret = -1;
  362. goto out;
  363. }
  364. ret = cfg_parser(buf, cfg_item_handler, cfg);
  365. out:
  366. if (buf)
  367. fm_free(buf);
  368. return ret;
  369. }
  370. static fm_s32 fm_cust_config_print(fm_cust_cfg *cfg)
  371. {
  372. fm_s32 i;
  373. WCN_DBG(FM_NTC | MAIN, "rssi_l:\t0x%04x\n", cfg->rx_cfg.long_ana_rssi_th);
  374. WCN_DBG(FM_NTC | MAIN, "rssi_s:\t0x%04x\n", cfg->rx_cfg.short_ana_rssi_th);
  375. WCN_DBG(FM_NTC | MAIN, "mr_th:\t0x%04x\n", cfg->rx_cfg.mr_th);
  376. WCN_DBG(FM_NTC | MAIN, "cqi_th:\t0x%04x\n", cfg->rx_cfg.cqi_th);
  377. WCN_DBG(FM_NTC | MAIN, "smg_th:\t0x%04x\n", cfg->rx_cfg.smg_th);
  378. WCN_DBG(FM_NTC | MAIN, "scan_ch_size:\t%d\n", cfg->rx_cfg.scan_ch_size);
  379. WCN_DBG(FM_NTC | MAIN, "seek_space:\t%d\n", cfg->rx_cfg.seek_space);
  380. WCN_DBG(FM_NTC | MAIN, "band:\t%d\n", cfg->rx_cfg.band);
  381. WCN_DBG(FM_NTC | MAIN, "band_freq_l:\t%d\n", cfg->rx_cfg.band_freq_l);
  382. WCN_DBG(FM_NTC | MAIN, "band_freq_h:\t%d\n", cfg->rx_cfg.band_freq_h);
  383. WCN_DBG(FM_NTC | MAIN, "scan_sort:\t%d\n", cfg->rx_cfg.scan_sort);
  384. WCN_DBG(FM_NTC | MAIN, "fake_ch_num:\t%d\n", cfg->rx_cfg.fake_ch_num);
  385. WCN_DBG(FM_NTC | MAIN, "fake_ch_rssi_th:\t%d\n", cfg->rx_cfg.fake_ch_rssi_th);
  386. for (i = 0; i < cfg->rx_cfg.fake_ch_num; i++)
  387. WCN_DBG(FM_NTC | MAIN, "fake_ch:\t%d\n", cfg->rx_cfg.fake_ch[i]);
  388. WCN_DBG(FM_NTC | MAIN, "de_emphasis:\t%d\n", cfg->rx_cfg.deemphasis);
  389. WCN_DBG(FM_NTC | MAIN, "osc_freq:\t%d\n", cfg->rx_cfg.osc_freq);
  390. WCN_DBG(FM_NTC | MAIN, "scan_hole_low:\t%d\n", cfg->tx_cfg.scan_hole_low);
  391. WCN_DBG(FM_NTC | MAIN, "scan_hole_high:\t%d\n", cfg->tx_cfg.scan_hole_high);
  392. WCN_DBG(FM_NTC | MAIN, "power_level:\t%d\n", cfg->tx_cfg.power_level);
  393. return 0;
  394. }
  395. fm_s32 fm_cust_config(const fm_s8 *filepath)
  396. {
  397. fm_s32 ret = 0;
  398. fm_s8 *filep = NULL;
  399. fm_s8 file_path[51] = { 0 };
  400. fm_cust_config_default(&fm_config);
  401. WCN_DBG(FM_NTC | MAIN, "FM default config\n");
  402. fm_cust_config_print(&fm_config);
  403. if (!filepath) {
  404. filep = FM_CUST_CFG_PATH;
  405. } else {
  406. memcpy(file_path, filepath, (strlen(filepath) > 50) ? 50 : strlen(filepath));
  407. filep = file_path;
  408. trim_path(&filep);
  409. }
  410. ret = fm_cust_config_file(filep, &fm_config);
  411. WCN_DBG(FM_NTC | MAIN, "FM cust config\n");
  412. fm_cust_config_print(&fm_config);
  413. return ret;
  414. }
  415. fm_u16 fm_cust_config_fetch(enum fm_cust_cfg_op op_code)
  416. {
  417. fm_u16 tmp = 0;
  418. fm_s32 i;
  419. static fm_s32 fake_ch_idx;
  420. switch (op_code) {
  421. /* For FM RX */
  422. case FM_CFG_RX_RSSI_TH_LONG:{
  423. tmp = fm_config.rx_cfg.long_ana_rssi_th;
  424. break;
  425. }
  426. case FM_CFG_RX_RSSI_TH_SHORT:{
  427. tmp = fm_config.rx_cfg.short_ana_rssi_th;
  428. break;
  429. }
  430. case FM_CFG_RX_CQI_TH:{
  431. tmp = fm_config.rx_cfg.cqi_th;
  432. break;
  433. }
  434. case FM_CFG_RX_MR_TH:{
  435. tmp = fm_config.rx_cfg.mr_th;
  436. break;
  437. }
  438. case FM_CFG_RX_SMG_TH:{
  439. tmp = fm_config.rx_cfg.smg_th;
  440. break;
  441. }
  442. case FM_CFG_RX_SCAN_CH_SIZE:{
  443. tmp = fm_config.rx_cfg.scan_ch_size;
  444. break;
  445. }
  446. case FM_CFG_RX_SEEK_SPACE:{
  447. tmp = fm_config.rx_cfg.seek_space;
  448. break;
  449. }
  450. case FM_CFG_RX_BAND:{
  451. tmp = fm_config.rx_cfg.band;
  452. break;
  453. }
  454. case FM_CFG_RX_BAND_FREQ_L:{
  455. tmp = fm_config.rx_cfg.band_freq_l;
  456. break;
  457. }
  458. case FM_CFG_RX_BAND_FREQ_H:{
  459. tmp = fm_config.rx_cfg.band_freq_h;
  460. break;
  461. }
  462. case FM_CFG_RX_SCAN_SORT:{
  463. tmp = fm_config.rx_cfg.scan_sort;
  464. break;
  465. }
  466. case FM_CFG_RX_FAKE_CH_NUM:{
  467. tmp = fm_config.rx_cfg.fake_ch_num;
  468. break;
  469. }
  470. case FM_CFG_RX_FAKE_CH:{
  471. tmp = fm_config.rx_cfg.fake_ch[fake_ch_idx];
  472. i = (fm_config.rx_cfg.fake_ch_num > 0) ? fm_config.rx_cfg.fake_ch_num : FAKE_CH_MAX;
  473. fake_ch_idx++;
  474. fake_ch_idx = fake_ch_idx % i;
  475. break;
  476. }
  477. case FM_CFG_RX_FAKE_CH_RSSI:{
  478. tmp = fm_config.rx_cfg.fake_ch_rssi_th;
  479. break;
  480. }
  481. case FM_CFG_RX_DEEMPHASIS:{
  482. tmp = fm_config.rx_cfg.deemphasis;
  483. break;
  484. }
  485. case FM_CFG_RX_OSC_FREQ:{
  486. tmp = fm_config.rx_cfg.osc_freq;
  487. break;
  488. }
  489. /* For FM TX */
  490. case FM_CFG_TX_SCAN_HOLE_LOW:{
  491. tmp = fm_config.tx_cfg.scan_hole_low;
  492. break;
  493. }
  494. case FM_CFG_TX_SCAN_HOLE_HIGH:{
  495. tmp = fm_config.tx_cfg.scan_hole_high;
  496. break;
  497. }
  498. case FM_CFG_TX_PWR_LEVEL:{
  499. tmp = fm_config.tx_cfg.power_level;
  500. break;
  501. }
  502. default:
  503. break;
  504. }
  505. WCN_DBG(FM_DBG | MAIN, "cust cfg %d: 0x%04x\n", op_code, tmp);
  506. return tmp;
  507. }