1 #include <linux/delay.h>
2 #include <linux/slab.h>
3 #include <linux/vmalloc.h>
8 #include "fm_typedef.h"
11 #include "fm_interface.h"
12 #include "fm_stdlib.h"
16 #include "fm_config.h"
17 #include "fm_private.h"
19 #include "mt6628_fm_reg.h"
20 #include "mt6628_fm.h"
21 //#include "mt6628_drv_dsp.h"
22 //#include "mt6628_fm_link.h"
23 #include "mt6628_fm_lib.h"
24 #include "mt6628_fm_cmd.h"
25 #include "mt6628_fm_cust_cfg.h"
26 extern fm_cust_cfg mt6628_fm_config;
28 #define MT6628_FM_PATCH_PATH "/etc/firmware/mt6628/mt6628_fm_patch.bin"
29 #define MT6628_FM_COEFF_PATH "/etc/firmware/mt6628/mt6628_fm_coeff.bin"
30 #define MT6628_FM_HWCOEFF_PATH "/etc/firmware/mt6628/mt6628_fm_hwcoeff.bin"
31 #define MT6628_FM_ROM_PATH "/etc/firmware/mt6628/mt6628_fm_rom.bin"
33 static struct fm_patch_tbl mt6628_patch_tbl[5] = {
34 {FM_ROM_V1, "/etc/firmware/mt6628/mt6628_fm_v1_patch.bin", "/etc/firmware/mt6628/mt6628_fm_v1_coeff.bin", NULL, NULL},
35 {FM_ROM_V2, "/etc/firmware/mt6628/mt6628_fm_v2_patch.bin", "/etc/firmware/mt6628/mt6628_fm_v2_coeff.bin", NULL, NULL},
36 {FM_ROM_V3, "/etc/firmware/mt6628/mt6628_fm_v3_patch.bin", "/etc/firmware/mt6628/mt6628_fm_v3_coeff.bin", NULL, NULL},
37 {FM_ROM_V4, "/etc/firmware/mt6628/mt6628_fm_v4_patch.bin", "/etc/firmware/mt6628/mt6628_fm_v4_coeff.bin", NULL, NULL},
38 {FM_ROM_V5, "/etc/firmware/mt6628/mt6628_fm_v5_patch.bin", "/etc/firmware/mt6628/mt6628_fm_v5_coeff.bin", NULL, NULL},
41 static struct fm_hw_info mt6628_hw_info = {
42 .chip_id = 0x00006628,
43 .eco_ver = 0x00000000,
44 .rom_ver = 0x00000000,
45 .patch_ver = 0x00000000,
46 .reserve = 0x00000000,
49 static struct fm_i2s_info mt6628_i2s_inf = {
50 .status = 0, //i2s off
51 .mode = 0, //slave mode
52 .rate = 48000, //48000 sample rate
55 #define PATCH_SEG_LEN 512
57 static fm_u8 *cmd_buf = NULL;
58 static struct fm_lock *cmd_buf_lock = NULL;
59 static struct fm_callback *fm_cb_op;
60 static struct fm_res_ctx *res = NULL;
61 //static fm_s32 Chip_Version = mt6628_E1;
63 //static fm_bool rssi_th_set = fm_false;
66 #undef MT6628_FM_USE_6626EVB
69 #ifdef MTK_FM_50KHZ_SUPPORT
70 static struct fm_fifo *cqi_fifo = NULL;
72 static fm_s32 mt6628_is_dese_chan(fm_u16 freq);
73 static fm_s32 mt6628_mcu_dese(fm_u16 freq, void *arg);
74 static fm_s32 mt6628_gps_dese(fm_u16 freq, void *arg);
75 static fm_u16 mt6628_chan_para_get(fm_u16 freq);
76 static fm_s32 mt6628_desense_check(fm_u16 freq,fm_s32 rssi);
77 static fm_s32 mt6628_I2s_Setting(fm_s32 onoff, fm_s32 mode, fm_s32 sample);
78 static fm_s32 mt6628_soft_mute_tune(fm_u16 freq,fm_s32 *rssi,fm_bool *valid);
79 static fm_s32 mt6628_pwron(fm_s32 data)
81 /*//Turn on FM on 6628 chip by WMT driver
82 if(MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_LPBK)){
83 WCN_DBG(FM_ALT|CHIP,"WMT turn on LPBK Fail!\n");
86 WCN_DBG(FM_ALT|CHIP,"WMT turn on LPBK OK!\n");
89 if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_FM)) {
90 WCN_DBG(FM_ALT | CHIP, "WMT turn on FM Fail!\n");
93 WCN_DBG(FM_ALT | CHIP, "WMT turn on FM OK!\n");
99 static fm_s32 mt6628_pwroff(fm_s32 data)
101 if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_off(WMTDRV_TYPE_FM)) {
102 WCN_DBG(FM_ALT | CHIP, "WMT turn off FM Fail!\n");
105 WCN_DBG(FM_NTC | CHIP, "WMT turn off FM OK!\n");
110 static fm_s32 Delayms(fm_u32 data)
112 WCN_DBG(FM_DBG | CHIP, "delay %dms\n", data);
117 static fm_s32 Delayus(fm_u32 data)
119 WCN_DBG(FM_DBG | CHIP, "delay %dus\n", data);
124 fm_s32 mt6628_get_read_result(struct fm_res_ctx* result)
132 static fm_s32 mt6628_read(fm_u8 addr, fm_u16 *val)
137 if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
138 pkt_size = mt6628_get_reg(cmd_buf, TX_BUF_SIZE, addr);
139 ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_FSPI_RD, SW_RETRY_CNT, FSPI_RD_TIMEOUT, mt6628_get_read_result);
145 FM_UNLOCK(cmd_buf_lock);
150 static fm_s32 mt6628_write(fm_u8 addr, fm_u16 val)
155 if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
156 pkt_size = mt6628_set_reg(cmd_buf, TX_BUF_SIZE, addr, val);
157 ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_FSPI_WR, SW_RETRY_CNT, FSPI_WR_TIMEOUT, NULL);
158 FM_UNLOCK(cmd_buf_lock);
163 static fm_s32 mt6628_set_bits(fm_u8 addr, fm_u16 bits, fm_u16 mask)
168 ret = mt6628_read(addr, &val);
173 val = ((val & (mask)) | bits);
174 ret = mt6628_write(addr, val);
179 static fm_u16 mt6628_get_chipid(void)
184 /* MT6628_SetAntennaType - set Antenna type
185 * @type - 1,Short Antenna; 0, Long Antenna
187 static fm_s32 mt6628_SetAntennaType(fm_s32 type)
191 WCN_DBG(FM_DBG | CHIP, "set ana to %s\n", type ? "short" : "long");
192 mt6628_read(FM_MAIN_CG2_CTRL, &dataRead);
195 dataRead |= ANTENNA_TYPE;
197 dataRead &= (~ANTENNA_TYPE);
200 mt6628_write(FM_MAIN_CG2_CTRL, dataRead);
205 static fm_s32 mt6628_GetAntennaType(void)
209 mt6628_read(FM_MAIN_CG2_CTRL, &dataRead);
210 WCN_DBG(FM_DBG | CHIP, "get ana type: %s\n", (dataRead&ANTENNA_TYPE) ? "short" : "long");
212 if (dataRead&ANTENNA_TYPE)
213 return FM_ANA_SHORT; //short antenna
215 return FM_ANA_LONG; //long antenna
219 static fm_s32 mt6628_Mute(fm_bool mute)
224 WCN_DBG(FM_DBG | CHIP, "set %s\n", mute ? "mute" : "unmute");
225 mt6628_read(FM_MAIN_CTRL, &dataRead);
228 ret = mt6628_write(FM_MAIN_CTRL, (dataRead&0xFFDF) | 0x0020);
230 ret = mt6628_write(FM_MAIN_CTRL, (dataRead&0xFFDF));
237 /*static fm_s32 mt6628_set_RSSITh(fm_u16 TH_long, fm_u16 TH_short)
239 mt6628_write(0xE2, 0x3072);
240 mt6628_write(0xE3, TH_long);
241 mt6628_write(0xE1, 0x0002);
243 mt6628_write(0xE2, 0x307A);
244 mt6628_write(0xE3, TH_short);
245 mt6628_write(0xE1, 0x0002);
247 WCN_DBG(FM_DBG | CHIP, "RSSI TH, long:0x%04x, short:0x%04x", TH_long, TH_short);
252 static fm_s32 mt6628_set_SMGTh(fm_s32 ver, fm_u16 TH_smg)
254 if (mt6628_E1 == ver) {
255 mt6628_write(0xE2, 0x321E);
256 mt6628_write(0xE3, TH_smg);
257 mt6628_write(0xE1, 0x0002);
259 mt6628_write(0xE2, 0x3218);
260 mt6628_write(0xE3, TH_smg);
261 mt6628_write(0xE1, 0x0002);
264 WCN_DBG(FM_DBG | CHIP, "Soft-mute gain TH %d\n", (int)TH_smg);
268 static fm_s32 mt6628_RampDown(void)
274 WCN_DBG(FM_DBG | CHIP, "ramp down\n");
276 mt6628_read(FM_MAIN_INTRMASK, &tmp);
277 mt6628_write(FM_MAIN_INTRMASK, 0x0000);
278 mt6628_write(0x6B, 0x0000);
280 if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
281 pkt_size = mt6628_rampdown(cmd_buf, TX_BUF_SIZE);
282 ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_RAMPDOWN, SW_RETRY_CNT, RAMPDOWN_TIMEOUT, NULL);
283 FM_UNLOCK(cmd_buf_lock);
286 WCN_DBG(FM_ERR | CHIP, "ramp down failed\n");
289 #ifdef MT6628_FM_FPGA
291 mt6628_write(0x54, 0x0001);
292 mt6628_write(0x11, 0x37D4);
293 mt6628_write(0x54, 0x8000);
295 mt6628_write(0x6B, 0x2100);
296 mt6628_write(FM_MAIN_INTRMASK, tmp);
300 static fm_s32 mt6628_get_rom_version(void)
304 //DSP rom code version request enable --- set 0x61 b15=1
305 mt6628_set_bits(0x61, 0x8000, 0x7FFF);
307 //Release ASIP reset --- set 0x61 b1=1
308 mt6628_set_bits(0x61, 0x0002, 0xFFFD);
310 //Enable ASIP power --- set 0x61 b0=0
311 mt6628_set_bits(0x61, 0x0000, 0xFFFE);
313 //Wait DSP code version ready --- wait 1ms
316 //Get FM DSP code version --- rd 0x83[15:8]
317 mt6628_read(0x83, &tmp);
320 //DSP rom code version request disable --- set 0x61 b15=0
321 mt6628_set_bits(0x61, 0x0000, 0x7FFF);
323 //Reset ASIP --- set 0x61[1:0] = 1
324 mt6628_set_bits(0x61, 0x0001, 0xFFFC);
326 WCN_DBG(FM_NTC | CHIP, "ROM version: v%d\n", (fm_s32)tmp);
330 static fm_s32 mt6628_get_patch_path(fm_s32 ver, const fm_s8 **ppath)
333 fm_s32 max = sizeof(mt6628_patch_tbl) / sizeof(mt6628_patch_tbl[0]);
335 //check if the ROM version is defined or not
336 for (i = 0; i < max; i++) {
337 if ((mt6628_patch_tbl[i].idx == ver) && (fm_file_exist(mt6628_patch_tbl[i].patch) == 0)) {
338 *ppath = mt6628_patch_tbl[i].patch;
339 WCN_DBG(FM_NTC | CHIP, "Get ROM version OK\n");
345 // the ROM version isn't defined, find a latest patch instead
346 for (i = max; i > 0; i--) {
347 if (fm_file_exist(mt6628_patch_tbl[i-1].patch) == 0) {
348 *ppath = mt6628_patch_tbl[i-1].patch;
349 WCN_DBG(FM_WAR | CHIP, "undefined ROM version\n");
355 WCN_DBG(FM_ERR | CHIP, "No valid patch file\n");
360 static fm_s32 mt6628_get_coeff_path(fm_s32 ver, const fm_s8 **ppath)
363 fm_s32 max = sizeof(mt6628_patch_tbl) / sizeof(mt6628_patch_tbl[0]);
365 //check if the ROM version is defined or not
366 for (i = 0; i < max; i++) {
367 if ((mt6628_patch_tbl[i].idx == ver) && (fm_file_exist(mt6628_patch_tbl[i].coeff) == 0)) {
368 *ppath = mt6628_patch_tbl[i].coeff;
369 WCN_DBG(FM_NTC | CHIP, "Get ROM version OK\n");
375 // the ROM version isn't defined, find a latest patch instead
376 for (i = max; i > 0; i--) {
377 if (fm_file_exist(mt6628_patch_tbl[i-1].coeff) == 0) {
378 *ppath = mt6628_patch_tbl[i-1].coeff;
379 WCN_DBG(FM_WAR | CHIP, "undefined ROM version\n");
385 WCN_DBG(FM_ERR | CHIP, "No valid coeff file\n");
391 * mt6628_DspPatch - DSP download procedure
392 * @img - source dsp bin code
393 * @len - patch length in byte
394 * @type - rom/patch/coefficient/hw_coefficient
396 static fm_s32 mt6628_DspPatch(const fm_u8 *img, fm_s32 len, enum IMG_TYPE type)
410 seg_num = len / PATCH_SEG_LEN + 1;
411 WCN_DBG(FM_NTC | CHIP, "binary len:%d, seg num:%d\n", len, seg_num);
416 for (seg_id = 0; seg_id < seg_num; seg_id++) {
417 seg_len = ((seg_id + 1) < seg_num) ? PATCH_SEG_LEN : (len % PATCH_SEG_LEN);
418 WCN_DBG(FM_NTC | CHIP, "rom,[seg_id:%d], [seg_len:%d]\n", seg_id, seg_len);
419 if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
420 pkt_size = mt6628_rom_download(cmd_buf, TX_BUF_SIZE, seg_num, seg_id, &img[seg_id*PATCH_SEG_LEN], seg_len);
421 WCN_DBG(FM_NTC | CHIP, "pkt_size:%d\n", (fm_s32)pkt_size);
422 ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_ROM, SW_RETRY_CNT, ROM_TIMEOUT, NULL);
423 FM_UNLOCK(cmd_buf_lock);
426 WCN_DBG(FM_ALT | CHIP, "mt6628_rom_download failed\n");
434 for (seg_id = 0; seg_id < seg_num; seg_id++) {
435 seg_len = ((seg_id + 1) < seg_num) ? PATCH_SEG_LEN : (len % PATCH_SEG_LEN);
436 WCN_DBG(FM_NTC | CHIP, "patch,[seg_id:%d], [seg_len:%d]\n", seg_id, seg_len);
437 if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
438 pkt_size = mt6628_patch_download(cmd_buf, TX_BUF_SIZE, seg_num, seg_id, &img[seg_id*PATCH_SEG_LEN], seg_len);
439 WCN_DBG(FM_NTC | CHIP, "pkt_size:%d\n", (fm_s32)pkt_size);
440 ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_PATCH, SW_RETRY_CNT, PATCH_TIMEOUT, NULL);
441 FM_UNLOCK(cmd_buf_lock);
444 WCN_DBG(FM_ALT | CHIP, "mt6628_patch_download failed\n");
450 case IMG_HW_COEFFICIENT:
452 for (seg_id = 0; seg_id < seg_num; seg_id++) {
453 seg_len = ((seg_id + 1) < seg_num) ? PATCH_SEG_LEN : (len % PATCH_SEG_LEN);
454 WCN_DBG(FM_NTC | CHIP, "hwcoeff,[seg_id:%d], [seg_len:%d]\n", seg_id, seg_len);
455 if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
456 pkt_size = mt6628_hwcoeff_download(cmd_buf, TX_BUF_SIZE, seg_num, seg_id, &img[seg_id*PATCH_SEG_LEN], seg_len);
457 WCN_DBG(FM_NTC | CHIP, "pkt_size:%d\n", (fm_s32)pkt_size);
458 ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_HWCOEFF, SW_RETRY_CNT, HWCOEFF_TIMEOUT, NULL);
459 FM_UNLOCK(cmd_buf_lock);
462 WCN_DBG(FM_ALT | CHIP, "mt6628_hwcoeff_download failed\n");
468 case IMG_COEFFICIENT:
470 for (seg_id = 0; seg_id < seg_num; seg_id++) {
471 seg_len = ((seg_id + 1) < seg_num) ? PATCH_SEG_LEN : (len % PATCH_SEG_LEN);
472 WCN_DBG(FM_NTC | CHIP, "coeff,[seg_id:%d], [seg_len:%d]\n", seg_id, seg_len);
473 if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
474 pkt_size = mt6628_coeff_download(cmd_buf, TX_BUF_SIZE, seg_num, seg_id, &img[seg_id*PATCH_SEG_LEN], seg_len);
475 WCN_DBG(FM_NTC | CHIP, "pkt_size:%d\n", (fm_s32)pkt_size);
476 ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_COEFF, SW_RETRY_CNT, COEFF_TIMEOUT, NULL);
477 FM_UNLOCK(cmd_buf_lock);
480 WCN_DBG(FM_ALT | CHIP, "mt6628_coeff_download failed\n");
494 static fm_s32 mt6628_PowerUp(fm_u16 *chip_id, fm_u16 *device_id)
496 #define PATCH_BUF_SIZE 4096*6
501 const fm_s8 *path_patch = NULL;
502 const fm_s8 *path_coeff = NULL;
503 //const fm_s8 *path_hwcoeff = NULL;
504 //fm_s32 coeff_len = 0;
505 fm_s32 patch_len = 0;
506 fm_u8 *dsp_buf = NULL;
509 FMR_ASSERT(device_id);
511 WCN_DBG(FM_DBG | CHIP, "pwr on seq......\n");
513 //Wholechip FM Power Up: step 1, FM Digital Clock enable
514 if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
515 pkt_size = mt6628_pwrup_clock_on(cmd_buf, TX_BUF_SIZE);
516 ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_EN, SW_RETRY_CNT, EN_TIMEOUT, NULL);
517 FM_UNLOCK(cmd_buf_lock);
520 WCN_DBG(FM_ALT | CHIP, "mt6628_pwrup_clock_on failed\n");
524 #ifdef FM_DIGITAL_INPUT
525 mt6628_I2s_Setting(MT6628_I2S_ON, MT6628_I2S_SLAVE, MT6628_I2S_44K);
526 mt_combo_audio_ctrl(COMBO_AUDIO_STATE_2);
529 //Wholechip FM Power Up: step 2, read HW version
530 mt6628_read(0x62, &tmp_reg);
531 mt6628_read(0x62, &tmp_reg);
533 *device_id = tmp_reg;
534 mt6628_hw_info.chip_id = (fm_s32)tmp_reg;
535 WCN_DBG(FM_NTC | CHIP, "chip_id:0x%04x\n", tmp_reg);
537 if (mt6628_hw_info.chip_id != 0x6628) {
538 WCN_DBG(FM_NTC | CHIP, "fm sys error, reset hw\n");
542 mt6628_hw_info.eco_ver = (fm_s32)mtk_wcn_wmt_hwver_get();
543 WCN_DBG(FM_NTC | CHIP, "ECO version:0x%08x\n", mt6628_hw_info.eco_ver);
544 mt6628_hw_info.eco_ver += 1;
546 //get mt6628 DSP rom version
547 if ((ret = mt6628_get_rom_version()) >= 0) {
548 mt6628_hw_info.rom_ver = ret;
549 WCN_DBG(FM_NTC | CHIP, "ROM version: v%d\n", mt6628_hw_info.rom_ver);
551 WCN_DBG(FM_ERR | CHIP, "get ROM version failed\n");
555 //Wholechip FM Power Up: step 3, download patch
556 if (!(dsp_buf = fm_vmalloc(PATCH_BUF_SIZE))) {
557 WCN_DBG(FM_ALT | CHIP, "-ENOMEM\n");
561 ret = mt6628_get_patch_path(mt6628_hw_info.rom_ver, &path_patch);
562 patch_len = fm_file_read(path_patch, dsp_buf, PATCH_BUF_SIZE, 0);
563 mt6628_DspPatch((const fm_u8*)dsp_buf, patch_len, IMG_PATCH);
565 ret = mt6628_get_coeff_path(mt6628_hw_info.rom_ver, &path_coeff);
566 patch_len = fm_file_read(path_coeff, dsp_buf, PATCH_BUF_SIZE, 0);
568 mt6628_hw_info.rom_ver += 1;
570 tmp_reg = dsp_buf[38] | (dsp_buf[39] << 8);
571 mt6628_hw_info.patch_ver = (fm_s32)tmp_reg;
572 WCN_DBG(FM_NTC | CHIP, "Patch version: 0x%08x\n", mt6628_hw_info.patch_ver);
575 dsp_buf[4] = 0x00; //if we found rom version undefined, we should disable patch
579 mt6628_DspPatch((const fm_u8*)dsp_buf, patch_len, IMG_COEFFICIENT);
580 mt6628_write(0x90, 0x0040);
581 mt6628_write(0x90, 0x0000);
588 //mt6628_check_dsp();
590 //Wholechip FM Power Up: step 4, FM Digital Init: fm_rgf_maincon
591 if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
592 pkt_size = mt6628_pwrup_digital_init(cmd_buf, TX_BUF_SIZE);
593 ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_EN, SW_RETRY_CNT, EN_TIMEOUT, NULL);
594 FM_UNLOCK(cmd_buf_lock);
596 WCN_DBG(FM_ALT | CHIP, "mt6628_pwrup_digital_init failed\n");
600 WCN_DBG(FM_NTC | CHIP, "pwr on seq ok\n");
602 //mt6628_check_dsp();
604 // rssi_th_set = fm_false;
608 static fm_s32 mt6628_PowerDown(void)
614 WCN_DBG(FM_DBG | CHIP, "pwr down seq\n");
615 /*SW work around for MCUFA issue.
616 *if interrupt happen before doing rampdown, DSP can't switch MCUFA back well.
617 * In case read interrupt, and clean if interrupt found before rampdown.
619 mt6628_read(FM_MAIN_INTR, &dataRead);
621 if (dataRead & 0x1) {
622 mt6628_write(FM_MAIN_INTR, dataRead);//clear status flag
627 #ifdef FM_DIGITAL_INPUT
628 mt6628_I2s_Setting(MT6628_I2S_OFF, MT6628_I2S_SLAVE, MT6628_I2S_44K);
631 if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
632 pkt_size = mt6628_pwrdown(cmd_buf, TX_BUF_SIZE);
633 ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_EN, SW_RETRY_CNT, EN_TIMEOUT, NULL);
634 FM_UNLOCK(cmd_buf_lock);
637 WCN_DBG(FM_ALT | CHIP, "mt6628_pwrdown failed\n");
641 //FIX_ME, disable ext interrupt
642 mt6628_write(FM_MAIN_EXTINTRMASK, 0x00);
644 // rssi_th_set = fm_false;
648 static fm_bool mt6628_SetFreq(fm_u16 freq)
652 fm_u16 chan_para = 0;
654 fm_cb_op->cur_freq_set(freq);
657 //MCU clock adjust if need
658 if ((ret = mt6628_mcu_dese(freq, NULL)) < 0)
660 WCN_DBG(FM_ERR | MAIN, "mt6628_mcu_dese FAIL:%d\n", ret);
663 WCN_DBG(FM_INF | MAIN, "MCU %d\n", ret);
665 //GPS clock adjust if need
666 if ((ret = mt6628_gps_dese(freq, NULL)) < 0)
668 WCN_DBG(FM_ERR | MAIN, "mt6628_gps_dese FAIL:%d\n", ret);
671 WCN_DBG(FM_INF | MAIN, "GPS %d\n", ret);
673 if (FM_LOCK(cmd_buf_lock)) return fm_false;
675 // if (fm_cb_op->chan_para_get) {
676 chan_para = mt6628_chan_para_get(freq);
677 WCN_DBG(FM_DBG | CHIP, "%d chan para = %d\n", (fm_s32)freq, (fm_s32)chan_para);
680 pkt_size = mt6628_tune(cmd_buf, TX_BUF_SIZE, freq, chan_para);
681 ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_TUNE | FLAG_TUNE_DONE, SW_RETRY_CNT, TUNE_TIMEOUT, NULL);
682 FM_UNLOCK(cmd_buf_lock);
685 WCN_DBG(FM_ALT | CHIP, "mt6628_tune failed\n");
689 WCN_DBG(FM_DBG | CHIP, "set freq to %d ok\n", freq);
691 /* if (rssi_th_set == fm_false) {
692 mt6628_set_RSSITh(MT6628fm_cust_config_fetch(FM_CFG_RX_RSSI_TH_LONG), MT6628fm_cust_config_fetch(FM_CFG_RX_RSSI_TH_SHORT));
693 mt6628_set_SMGTh(Chip_Version, MT6628fm_cust_config_fetch(FM_CFG_RX_SMG_TH));
694 rssi_th_set = fm_true;
703 * @pFreq - IN/OUT parm, IN start freq/OUT seek valid freq
704 * @seekdir - 0:up, 1:down
705 * @space - 1:50KHz, 2:100KHz, 4:200KHz
706 * return fm_true:seek success; fm_false:seek failed
708 static fm_bool mt6628_Seek(fm_u16 min_freq, fm_u16 max_freq, fm_u16 *pFreq, fm_u16 seekdir, fm_u16 space)
711 fm_u16 pkt_size,temp;
714 mt6628_read(FM_MAIN_CTRL, &temp);
715 mt6628_Mute(fm_true);
717 if (FM_LOCK(cmd_buf_lock)) return fm_false;
718 pkt_size = mt6628_seek(cmd_buf, TX_BUF_SIZE, seekdir, space, max_freq, min_freq);
719 ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_SEEK | FLAG_SEEK_DONE, SW_RETRY_CNT, SEEK_TIMEOUT, mt6628_get_read_result);
720 FM_UNLOCK(cmd_buf_lock);
723 *pFreq = res->seek_result;
724 //fm_cb_op->cur_freq_set(*pFreq);
726 WCN_DBG(FM_ALT | CHIP, "mt6628_seek failed\n");
730 //get the result freq
731 WCN_DBG(FM_NTC | CHIP, "seek, result freq:%d\n", *pFreq);
733 if((temp&0x0020) == 0)
735 mt6628_Mute(fm_false);
741 #define FM_CQI_LOG_PATH "/mnt/sdcard/fmcqilog"
743 static fm_s32 mt6628_full_cqi_get(fm_s32 min_freq, fm_s32 max_freq, fm_s32 space, fm_s32 cnt)
747 fm_u16 freq, orig_freq;
749 fm_s32 space_val, max, min, num;
750 struct mt6628_full_cqi *p_cqi;
751 fm_u8 *cqi_log_title = "Freq, RSSI, PAMD, PR, FPAMD, MR, ATDC, PRX, ATDEV, SMGain, DltaRSSI\n";
752 fm_u8 cqi_log_buf[100] = {0};
754 fm_u8 cqi_log_path[100] = {0};
756 WCN_DBG(FM_NTC | CHIP, "6628 cqi log start\n");
757 // for soft-mute tune, and get cqi
758 freq = fm_cb_op->cur_freq_get();
759 if (0 == fm_get_channel_space(freq)) {
764 if (0 == fm_get_channel_space(min_freq)) {
769 if (0 == fm_get_channel_space(max_freq)) {
774 if (space == 0x0001) {
775 space_val = 5; // 50Khz
776 } else if (space == 0x0002) {
777 space_val = 10; // 100Khz
778 } else if (space == 0x0004) {
779 space_val = 20; // 200Khz
783 num = (max - min) / space_val + 1; //Eg, (8760 - 8750) / 10 + 1 = 2
784 for (k = 0; (10000 == orig_freq) && (0xffffffff == g_dbg_level) && (k < cnt); k++)
786 WCN_DBG(FM_NTC | CHIP, "cqi file:%d\n", k+1);
789 fm_memcpy(cqi_log_path, FM_CQI_LOG_PATH, strlen(FM_CQI_LOG_PATH));
790 sprintf(&cqi_log_path[strlen(FM_CQI_LOG_PATH)], "%d.txt", k+1);
791 fm_file_write(cqi_log_path, cqi_log_title, strlen(cqi_log_title), &pos);
792 for (j = 0; j < num; j++)
794 if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
795 pkt_size = mt6628_full_cqi_req(cmd_buf, TX_BUF_SIZE, &freq, 1, 1);
796 ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_SM_TUNE, SW_RETRY_CNT, SM_TUNE_TIMEOUT, mt6628_get_read_result);
797 FM_UNLOCK(cmd_buf_lock);
800 WCN_DBG(FM_NTC | CHIP, "smt cqi size %d\n", res->cqi[0]);
801 p_cqi = (struct mt6628_full_cqi*)&res->cqi[2];
802 for (i = 0; i < res->cqi[1]; i++) {
804 WCN_DBG(FM_NTC | CHIP, "freq %d, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x\n",
817 sprintf(cqi_log_buf, "%04d,%04x,%04x,%04x,%04x,%04x,%04x,%04x,%04x,%04x,%04x,\n",
829 // write back to log file
830 fm_file_write(cqi_log_path, cqi_log_buf, strlen(cqi_log_buf), &pos);
835 WCN_DBG(FM_ALT | CHIP, "smt get CQI failed\n");
840 fm_cb_op->cur_freq_set(0);//avoid run too much times
842 WCN_DBG(FM_NTC | CHIP, "6628 cqi log done\n");
848 static fm_bool mt6628_Scan(fm_u16 min_freq, fm_u16 max_freq, fm_u16 *pFreq, fm_u16 *pScanTBL,
849 fm_u16 *ScanTBLsize, fm_u16 scandir, fm_u16 space)
852 fm_u16 pkt_size,temp;
854 fm_u16 tmp_scanTBLsize = *ScanTBLsize;
856 if ((!pScanTBL) || (tmp_scanTBLsize == 0)) {
857 WCN_DBG(FM_ALT | CHIP, "scan, failed:invalid scan table\n");
861 WCN_DBG(FM_NTC | CHIP, "start freq: %d, max_freq:%d, min_freq:%d, scan BTL size:%d, scandir:%d, space:%d\n", *pFreq, max_freq, min_freq, *ScanTBLsize, scandir, space);
864 mt6628_read(FM_MAIN_CTRL, &temp);
865 mt6628_Mute(fm_true);
867 mt6628_full_cqi_get(min_freq, max_freq, space, 5);
870 if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
871 pkt_size = mt6628_scan(cmd_buf, TX_BUF_SIZE, scandir, space, max_freq, min_freq);
872 ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_SCAN | FLAG_SCAN_DONE, SW_RETRY_CNT, SCAN_TIMEOUT, mt6628_get_read_result);
873 FM_UNLOCK(cmd_buf_lock);
876 fm_memcpy(pScanTBL, res->scan_result, sizeof(fm_u16)*FM_SCANTBL_SIZE);
877 WCN_DBG(FM_NTC | CHIP, "Rx scan result:\n");
879 for (offset = 0; offset < tmp_scanTBLsize; offset++) {
880 WCN_DBG(FM_NTC | CHIP, "%d: %04x\n", (fm_s32)offset, *(pScanTBL + offset));
883 *ScanTBLsize = tmp_scanTBLsize;
885 WCN_DBG(FM_ALT | CHIP, "mt6628_scan failed\n");
889 mt6628_set_bits(FM_MAIN_CTRL, 0x0000, 0xFFF0); //make sure tune/seek/scan/cqi bits = 0
890 if((temp&0x0020) == 0)
892 mt6628_Mute(fm_false);
898 //add for scan cancel case
899 static fm_bool cqi_abort = fm_false;
901 static fm_s32 mt6628_CQI_Get(fm_s8 *buf, fm_s32 buf_len)
906 struct mt6628_fm_cqi *pmt6628_cqi;
907 struct adapt_fm_cqi *pcqi;
909 if (!buf || buf_len < FM_CQI_BUF_SIZE) {
913 if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
914 pkt_size = mt6628_cqi_get(cmd_buf, TX_BUF_SIZE);
915 if (cqi_abort == fm_true) {
916 cqi_abort = fm_false;
919 ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_SCAN | FLAG_CQI_DONE, SW_RETRY_CNT, SCAN_TIMEOUT, mt6628_get_read_result);
921 FM_UNLOCK(cmd_buf_lock);
925 pmt6628_cqi = (struct mt6628_fm_cqi*)res->cqi;
926 pcqi = (struct adapt_fm_cqi*)buf;
928 for (i = 0; i < (sizeof(res->cqi) / sizeof(struct mt6628_fm_cqi)); i++) {
929 pcqi[i].ch = (pmt6628_cqi[i].ch * 10 / 2) + 6400;
930 pcqi[i].rssi = (fm_s32)pmt6628_cqi[i].rssi;
932 if (pcqi[i].rssi >= 32768) {
933 pcqi[i].rssi = pcqi[i].rssi - 65536;
936 pcqi[i].rssi = ((pcqi[i].rssi * 6) >> 4);
937 WCN_DBG(FM_NTC | CHIP, "%d --> %d(dbm)\n", pcqi[i].ch, pcqi[i].rssi);
940 WCN_DBG(FM_ALT | CHIP, "mt6628 get CQI failed:%d\n",ret);
943 mt6628_set_bits(FM_MAIN_CTRL, 0x0000, 0xFFF0); //make sure tune/seek/scan/cqi bits = 0
948 static fm_bool scan_abort = fm_false;
950 #ifdef MTK_FM_50KHZ_SUPPORT
951 #define SCAN_SEG_LEN 250
952 static fm_s8 raw_buf[16 * sizeof(struct adapt_fm_cqi)] = {0};
954 static fm_bool mt6628_Scan_50KHz(fm_u16 min_freq, fm_u16 max_freq, fm_u16 *pFreq, fm_u16 *pScanTBL,
955 fm_u16 *ScanTBLsize, fm_u16 scandir, fm_u16 space)
961 fm_u16 scan_tbl[FM_SCANTBL_SIZE]; //need no less than the chip
962 fm_s32 start_freq, end_freq;
963 fm_s32 ch_offset, step, tmp_val;
965 fm_s32 word_offset, bit_offset;
966 fm_s32 space_val = 5;
967 struct adapt_fm_cqi *pCQI = (struct adapt_fm_cqi *)raw_buf;
969 if (space == 0x0001) {
970 space_val = 5; // 50Khz
971 } else if (space == 0x0002) {
972 space_val = 10; // 100Khz
973 } else if (space == 0x0004) {
974 space_val = 20; // 200Khz
977 // calculate segment number
978 num = (max_freq - min_freq) / space_val; //Eg, (10800 - 8750) / 5 = 410
979 seg = (num / SCAN_SEG_LEN) + ((num % SCAN_SEG_LEN) ? 1 : 0); //Eg, (410 / 200) + ((410 % 200) ? 1 : 0) = 2 + 1 = 3
981 FM_FIFO_RESET(cqi_fifo);
982 fm_memset(pScanTBL, 0, sizeof(fm_u16) * (*ScanTBLsize));
985 scan_abort = fm_false; // reset scan cancel flag
986 for (i = 0; i < seg; i++) {
987 start_freq = min_freq + SCAN_SEG_LEN * space_val * i;
988 end_freq = min_freq + SCAN_SEG_LEN * space_val * (i + 1) - space_val;
989 end_freq = (end_freq > max_freq) ? max_freq : end_freq;
992 if (fm_true == scan_abort) {
993 scan_abort = fm_false;
997 if (fm_false == mt6628_Scan(start_freq, end_freq, pFreq, scan_tbl, ScanTBLsize, scandir, space)) {
1001 // get channel count
1002 for (ch_offset = 0; ch_offset < FM_SCANTBL_SIZE; ch_offset++) {
1003 if (scan_tbl[ch_offset] == 0)
1005 for (step = 0; step < 16; step++) {
1006 if (scan_tbl[ch_offset] & (1 << step)) {
1007 tmp_val = start_freq + (ch_offset * 16 + step) * space_val;
1008 WCN_DBG(FM_NTC | CHIP, "freq %d, end freq %d\n", tmp_val, end_freq);
1009 if (tmp_val <= end_freq) {
1012 word_offset = (tmp_val - min_freq) / space_val / 16;
1013 bit_offset = (tmp_val - min_freq) / space_val % 16;
1014 if ((word_offset < 26) && (word_offset >= 0)) {
1015 pScanTBL[word_offset] |= (1 << bit_offset);
1017 WCN_DBG(FM_NTC | CHIP, "cnt %d, word %d, bit %d\n", chl_cnt, word_offset, bit_offset);
1024 while (chl_cnt > 0) {
1025 ret = mt6628_CQI_Get(raw_buf, 16 * sizeof(struct adapt_fm_cqi));
1030 // add valid channel to cqi_fifo
1031 for (j = 0; j < sizeof(raw_buf) / sizeof(struct adapt_fm_cqi); j++) {
1032 if ((pCQI[j].ch >= start_freq) && (pCQI[j].ch <= end_freq)) {
1033 FM_FIFO_INPUT(cqi_fifo, pCQI + j);
1034 WCN_DBG(FM_NTC | CHIP, "%d %d(dbm) add to fifo\n", pCQI[j].ch, pCQI[j].rssi);
1046 static fm_s32 mt6628_CQI_Get_50KHz(fm_s8 *buf, fm_s32 buf_len)
1050 struct adapt_fm_cqi tmp = {
1054 struct adapt_fm_cqi *pcqi = (struct adapt_fm_cqi *)buf;
1057 if (!buf || buf_len < FM_CQI_BUF_SIZE) {
1061 for (i = 0; ((i < (buf_len / sizeof(struct adapt_fm_cqi))) && \
1062 (fm_false == FM_FIFO_IS_EMPTY(cqi_fifo))); i++) {
1063 FM_FIFO_OUTPUT(cqi_fifo, &tmp);
1064 pcqi[i].ch = tmp.ch;
1065 pcqi[i].rssi = tmp.rssi;
1066 WCN_DBG(FM_NTC | CHIP, "%d %d(dbm) get from fifo\n", pcqi[i].ch, pcqi[i].rssi);
1072 #endif //MTK_FM_50KHZ_SUPPORT
1076 * mt6628_GetCurRSSI - get current freq's RSSI value
1078 * If RS>511, then RSSI(dBm)= (RS-1024)/16*6
1079 * else RSSI(dBm)= RS/16*6
1081 static fm_s32 mt6628_GetCurRSSI(fm_s32 *pRSSI)
1085 mt6628_read(FM_RSSI_IND, &tmp_reg);
1086 tmp_reg = tmp_reg & 0x03ff;
1089 *pRSSI = (tmp_reg > 511) ? (((tmp_reg - 1024) * 6) >> 4) : ((tmp_reg * 6) >> 4);
1090 WCN_DBG(FM_DBG | CHIP, "rssi:%d, dBm:%d\n", tmp_reg, *pRSSI);
1092 WCN_DBG(FM_ERR | CHIP, "get rssi para error\n");
1099 static fm_u16 mt6628_vol_tbl[16] = { \
1100 0x0000, 0x0519, 0x066A, 0x0814, \
1101 0x0A2B, 0x0CCD, 0x101D, 0x1449, \
1102 0x198A, 0x2027, 0x287A, 0x32F5, \
1103 0x4027, 0x50C3, 0x65AD, 0x7FFF
1105 static fm_s32 mt6628_SetVol(fm_u8 vol)
1109 vol = (vol > 15) ? 15 : vol;
1110 ret = mt6628_write(0x7D, mt6628_vol_tbl[vol]);
1112 WCN_DBG(FM_ERR | CHIP, "Set vol=%d Failed\n", vol);
1115 WCN_DBG(FM_DBG | CHIP, "Set vol=%d OK\n", vol);
1119 fm_print_cmd_fifo(); //just for debug
1120 fm_print_evt_fifo();
1125 static fm_s32 mt6628_GetVol(fm_u8 *pVol)
1133 ret = mt6628_read(0x7D, &tmp);
1136 WCN_DBG(FM_ERR | CHIP, "Get vol Failed\n");
1140 for (i = 0; i < 16; i++) {
1141 if (mt6628_vol_tbl[i] == tmp) {
1147 WCN_DBG(FM_DBG | CHIP, "Get vol=%d OK\n", *pVol);
1151 static fm_s32 mt6628_dump_reg(void)
1155 for(i=0; i<0xff; i++)
1157 mt6628_read(i, &TmpReg);
1158 WCN_DBG(FM_NTC | CHIP, "0x%02x=0x%04x\n",i,TmpReg);
1163 static fm_bool mt6628_GetMonoStereo(fm_u16 *pMonoStereo)
1165 #define FM_BF_STEREO 0x1000
1169 mt6628_read(FM_RSSI_IND, &TmpReg);
1170 *pMonoStereo = (TmpReg & FM_BF_STEREO) >> 12;
1172 WCN_DBG(FM_ERR | CHIP, "MonoStero: para err\n");
1176 WCN_DBG(FM_DBG | CHIP, "MonoStero:0x%04x\n", *pMonoStereo);
1180 static fm_s32 mt6628_SetMonoStereo(fm_s32 MonoStereo)
1183 #define FM_FORCE_MS 0x0008
1185 WCN_DBG(FM_DBG | CHIP, "set to %s\n", MonoStereo ? "mono" : "auto");
1187 mt6628_write(0x60, 0x3007);
1190 ret = mt6628_set_bits(0x75, FM_FORCE_MS, ~FM_FORCE_MS);
1192 ret = mt6628_set_bits(0x75, 0x0000, ~FM_FORCE_MS);
1198 static fm_s32 mt6628_GetCapArray(fm_s32 *ca)
1204 mt6628_read(0x60, &tmp);
1205 mt6628_write(0x60, tmp&0xFFF7); //0x60 D3=0
1207 mt6628_read(0x26, &dataRead);
1210 mt6628_write(0x60, tmp); //0x60 D3=1
1215 * mt6628_GetCurPamd - get current freq's PAMD value
1217 * If PA>511 then PAMD(dB)= (PA-1024)/16*6,
1218 * else PAMD(dB)=PA/16*6
1220 static fm_bool mt6628_GetCurPamd(fm_u16 *pPamdLevl)
1223 fm_u16 dBvalue,valid_cnt=0;
1225 for (i = 0; i < 8; i++)
1227 if (mt6628_read(FM_ADDR_PAMD, &tmp_reg))
1234 dBvalue = (tmp_reg > 256) ? ((512 - tmp_reg) * 6 / 16) : 0;
1239 WCN_DBG(FM_DBG | CHIP, "[%d]PAMD=%d\n",i,dBvalue);
1245 *pPamdLevl = total/valid_cnt;
1251 WCN_DBG(FM_NTC | CHIP, "PAMD=%d\n", *pPamdLevl);
1255 static fm_s32 mt6628_ScanStop(void)
1257 cqi_abort = fm_true;
1258 scan_abort = fm_true;
1259 fm_force_active_event(FLAG_SCAN_DONE | FLAG_CQI_DONE);
1264 static fm_s32 mt6628_SeekStop(void)
1266 return fm_force_active_event(FLAG_SEEK_DONE);
1271 * mt6628_I2s_Setting - set the I2S state on MT6628
1272 * @onoff - I2S on/off
1273 * @mode - I2S mode: Master or Slave
1275 * Return:0, if success; error code, if failed
1277 static fm_s32 mt6628_I2s_Setting(fm_s32 onoff, fm_s32 mode, fm_s32 sample)
1279 fm_u16 tmp_state = 0;
1280 fm_u16 tmp_mode = 0;
1281 fm_u16 tmp_sample = 0;
1284 if (onoff == MT6628_I2S_ON) {
1285 tmp_state = 0x0080; //I2S Frequency tracking on, 0x61 D7=1
1286 mt6628_i2s_inf.status = 1;
1287 } else if (onoff == MT6628_I2S_OFF) {
1288 tmp_state = 0x0000; //I2S Frequency tracking off, 0x61 D7=0
1289 mt6628_i2s_inf.status = 0;
1291 WCN_DBG(FM_ERR | CHIP, "%s():[onoff=%d]\n", __func__, onoff);
1296 if (mode == MT6628_I2S_MASTER) {
1297 tmp_mode = 0x0000; //6620 as I2S master, set 0x9B D3=0
1298 mt6628_i2s_inf.mode = 1;
1299 } else if (mode == MT6628_I2S_SLAVE) {
1300 tmp_mode = 0x0008; //6620 as I2S slave, set 0x9B D3=1
1301 mt6628_i2s_inf.mode = 0;
1303 WCN_DBG(FM_ERR | CHIP, "%s():[mode=%d]\n", __func__, mode);
1308 if (sample == MT6628_I2S_32K) {
1309 tmp_sample = 0x0000; //6620 I2S 32KHz sample rate, 0x5F D11~12
1310 mt6628_i2s_inf.rate = 32000;
1311 } else if (sample == MT6628_I2S_44K) {
1312 tmp_sample = 0x0800; //6620 I2S 44.1KHz sample rate
1313 mt6628_i2s_inf.rate = 44100;
1314 } else if (sample == MT6628_I2S_48K) {
1315 tmp_sample = 0x1000; //6620 I2S 48KHz sample rate
1316 mt6628_i2s_inf.rate = 48000;
1318 WCN_DBG(FM_ERR | CHIP, "%s():[sample=%d]\n", __func__, sample);
1323 if ((ret = mt6628_set_bits(0x5F, tmp_sample, 0xE7FF)))
1326 if ((ret = mt6628_set_bits(0x9B, tmp_mode, 0xFFF7)))
1329 if ((ret = mt6628_set_bits(0x61, tmp_state, 0xFF7F)))
1332 WCN_DBG(FM_NTC | CHIP, "[onoff=%s][mode=%s][sample=%d](0)33KHz,(1)44.1KHz,(2)48KHz\n",
1333 (onoff == MT6628_I2S_ON) ? "On" : "Off",
1334 (mode == MT6628_I2S_MASTER) ? "Master" : "Slave",
1342 static fm_s32 mt6628_i2s_info_get(fm_s32 *ponoff, fm_s32 *pmode, fm_s32 *psample)
1346 FMR_ASSERT(psample);
1348 *ponoff = mt6628_i2s_inf.status;
1349 *pmode = mt6628_i2s_inf.mode;
1350 *psample = mt6628_i2s_inf.rate;
1356 static fm_s32 mt6628_hw_info_get(struct fm_hw_info *req)
1360 req->chip_id = mt6628_hw_info.chip_id;
1361 req->eco_ver = mt6628_hw_info.eco_ver;
1362 req->patch_ver = mt6628_hw_info.patch_ver;
1363 req->rom_ver = mt6628_hw_info.rom_ver;
1368 static fm_s32 mt6628_soft_mute_tune(fm_u16 freq,fm_s32 *rssi,fm_bool *valid)
1372 //fm_u16 freq;//, orig_freq;
1373 struct mt6628_full_cqi *p_cqi;
1374 fm_s32 RSSI=0, PAMD=0,MR=0, ATDC=0;
1375 fm_u32 PRX=0,ATDEV=0;
1376 fm_u16 softmuteGainLvl=0;
1378 if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
1379 pkt_size = mt6628_full_cqi_req(cmd_buf, TX_BUF_SIZE, &freq, 1, 1);
1380 ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_SM_TUNE, SW_RETRY_CNT, SM_TUNE_TIMEOUT, mt6628_get_read_result);
1381 FM_UNLOCK(cmd_buf_lock);
1385 WCN_DBG(FM_NTC | CHIP, "smt cqi size %d\n", res->cqi[0]);
1386 p_cqi = (struct mt6628_full_cqi*)&res->cqi[2];
1388 WCN_DBG(FM_NTC | CHIP, "freq %d, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x\n",
1400 RSSI = ((p_cqi->rssi & 0x03FF) >= 512) ? ((p_cqi->rssi & 0x03FF) - 1024) : (p_cqi->rssi & 0x03FF);
1401 PAMD = ((p_cqi->pamd & 0x1FF) >= 256) ? ((p_cqi->pamd & 0x01FF) - 512) : (p_cqi->pamd & 0x01FF);
1402 MR = ((p_cqi->mr & 0x01FF) >= 256) ? ((p_cqi->mr & 0x01FF) - 512) : (p_cqi->mr & 0x01FF);
1403 ATDC =(p_cqi->atdc >= 32768) ? (65536 - p_cqi->atdc) : (p_cqi->atdc);
1406 ATDC = (~(ATDC)) - 1;//Get abs value of ATDC
1408 PRX = (p_cqi->prx & 0x00FF);
1409 ATDEV = p_cqi->atdev;
1410 softmuteGainLvl = p_cqi->smg;
1411 //check if the channel is valid according to each CQIs
1412 if((RSSI >= mt6628_fm_config.rx_cfg.long_ana_rssi_th)
1413 && (PAMD <= mt6628_fm_config.rx_cfg.pamd_th)
1414 && (ATDC <= mt6628_fm_config.rx_cfg.atdc_th)
1415 && (MR >= mt6628_fm_config.rx_cfg.mr_th)
1416 && (PRX >= mt6628_fm_config.rx_cfg.prx_th)
1417 && (ATDEV >= mt6628_fm_config.rx_cfg.atdev_th)
1418 && (softmuteGainLvl >= mt6628_fm_config.rx_cfg.smg_th))
1428 WCN_DBG(FM_NTC | CHIP, "rssi\n");
1430 WCN_DBG(FM_NTC | CHIP, "PAMD\n");
1431 else if(ATDC > 3496)
1432 WCN_DBG(FM_NTC | CHIP, "ATDC\n");
1434 WCN_DBG(FM_NTC | CHIP, "MR\n");
1436 WCN_DBG(FM_NTC | CHIP, "PRX\n");
1437 else if(ATDEV < ATDC)
1438 WCN_DBG(FM_NTC | CHIP, "ATDEV\n");
1439 else if(softmuteGainLvl < 16421)
1440 WCN_DBG(FM_NTC | CHIP, "softmuteGainLvl\n");
1445 WCN_DBG(FM_ALT | CHIP, "smt get CQI failed\n");
1448 WCN_DBG(FM_NTC | CHIP, "valid=%d\n",*valid);
1452 static fm_bool mt6628_em_test(fm_u16 group_idx, fm_u16 item_idx, fm_u32 item_value)
1457 static fm_s32 MT6628fm_low_power_wa_default(fm_s32 fmon)
1462 fm_s32 MT6628fm_low_ops_register(struct fm_lowlevel_ops *ops)
1468 FMR_ASSERT(ops->cb.cur_freq_get);
1469 FMR_ASSERT(ops->cb.cur_freq_set);
1470 fm_cb_op = &ops->cb;
1472 ops->bi.low_pwr_wa = MT6628fm_low_power_wa_default;
1473 ops->bi.pwron = mt6628_pwron;
1474 ops->bi.pwroff = mt6628_pwroff;
1475 ops->bi.msdelay = Delayms;
1476 ops->bi.usdelay = Delayus;
1477 ops->bi.read = mt6628_read;
1478 ops->bi.write = mt6628_write;
1479 ops->bi.setbits = mt6628_set_bits;
1480 ops->bi.chipid_get = mt6628_get_chipid;
1481 ops->bi.mute = mt6628_Mute;
1482 ops->bi.rampdown = mt6628_RampDown;
1483 ops->bi.pwrupseq = mt6628_PowerUp;
1484 ops->bi.pwrdownseq = mt6628_PowerDown;
1485 ops->bi.setfreq = mt6628_SetFreq;
1486 ops->bi.seek = mt6628_Seek;
1487 ops->bi.seekstop = mt6628_SeekStop;
1488 ops->bi.scan = mt6628_Scan;
1489 ops->bi.cqi_get = mt6628_CQI_Get;
1490 #ifdef MTK_FM_50KHZ_SUPPORT
1491 ops->bi.scan = mt6628_Scan_50KHz;
1492 ops->bi.cqi_get = mt6628_CQI_Get_50KHz;
1494 ops->bi.scanstop = mt6628_ScanStop;
1495 ops->bi.rssiget = mt6628_GetCurRSSI;
1496 ops->bi.volset = mt6628_SetVol;
1497 ops->bi.volget = mt6628_GetVol;
1498 ops->bi.dumpreg = mt6628_dump_reg;
1499 ops->bi.msget = mt6628_GetMonoStereo;
1500 ops->bi.msset = mt6628_SetMonoStereo;
1501 ops->bi.pamdget = mt6628_GetCurPamd;
1502 ops->bi.em = mt6628_em_test;
1503 ops->bi.anaswitch = mt6628_SetAntennaType;
1504 ops->bi.anaget = mt6628_GetAntennaType;
1505 ops->bi.caparray_get = mt6628_GetCapArray;
1506 ops->bi.i2s_set = mt6628_I2s_Setting;
1507 ops->bi.hwinfo_get = mt6628_hw_info_get;
1508 ops->bi.i2s_get = mt6628_i2s_info_get;
1509 ops->bi.is_dese_chan = mt6628_is_dese_chan;
1510 ops->bi.softmute_tune = mt6628_soft_mute_tune;
1511 ops->bi.desense_check = mt6628_desense_check;
1512 ops->bi.cqi_log = mt6628_full_cqi_get;
1514 cmd_buf_lock = fm_lock_create("28_cmd");
1515 ret = fm_lock_get(cmd_buf_lock);
1517 cmd_buf = fm_zalloc(TX_BUF_SIZE + 1);
1520 WCN_DBG(FM_ALT | CHIP, "6628 fm lib alloc tx buf failed\n");
1524 #ifdef MTK_FM_50KHZ_SUPPORT
1525 cqi_fifo = fm_fifo_create("6628_cqi_fifo", sizeof(struct adapt_fm_cqi), 640);
1527 WCN_DBG(FM_ALT | CHIP, "6628 fm lib create cqi fifo failed\n");
1535 fm_s32 MT6628fm_low_ops_unregister(struct fm_lowlevel_ops *ops)
1541 #ifdef MTK_FM_50KHZ_SUPPORT
1542 fm_fifo_release(cqi_fifo);
1550 ret = fm_lock_put(cmd_buf_lock);
1551 fm_memset(&ops->bi, 0, sizeof(struct fm_basic_interface));
1554 //static struct fm_pub pub;
1555 //static struct fm_pub_cb *pub_cb = &pub.pub_tbl;
1557 static const fm_u16 mt6628_mcu_dese_list[] = {
1558 7630, 7800, 7940, 8320, 9260, 9600, 9710, 9920, 10400, 10410
1561 static const fm_u16 mt6628_gps_dese_list[] = {
1565 static const fm_s8 mt6628_chan_para_map[] = {
1566 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, //7600~7695
1567 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //7700~7795
1568 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //7800~7895
1569 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //7900~7995
1570 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //8000~8095
1571 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //8100~8195
1572 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //8200~8295
1573 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //8300~8395
1574 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, //8400~8495
1575 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //8500~8595
1576 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //8600~8695
1577 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //8700~8795
1578 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //8800~8895
1579 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //8900~8995
1580 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //9000~9095
1581 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //9100~9195
1582 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //9200~9295
1583 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //9300~9395
1584 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, //9400~9495
1585 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, //9500~9595
1586 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //9600~9695
1587 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //9700~9795
1588 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //9800~9895
1589 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, //9900~9995
1590 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10000~10095
1591 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10100~10195
1592 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, //10200~10295
1593 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10300~10395
1594 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10400~10495
1595 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10500~10595
1596 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10600~10695
1597 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, //10700~10795
1602 static const fm_u16 mt6628_scan_dese_list[] = {
1603 7680, 8210, 8450, 9210, 9220, 9600, 9840, 10400, 10750, 10760
1606 // return value: 0, not a de-sense channel; 1, this is a de-sense channel; else error no
1607 static fm_s32 mt6628_is_dese_chan(fm_u16 freq)
1611 size = sizeof(mt6628_scan_dese_list) / sizeof(mt6628_scan_dese_list[0]);
1613 if (0 == fm_get_channel_space(freq)) {
1618 if (mt6628_scan_dese_list[size -1] == freq)
1628 1, is desense channel and rssi is less than threshold;
1629 0, not desense channel or it is but rssi is more than threshold.*/
1630 static fm_s32 mt6628_desense_check(fm_u16 freq,fm_s32 rssi)
1632 if(mt6628_is_dese_chan(freq))
1634 if(rssi<mt6628_fm_config.rx_cfg.desene_rssi_th)
1638 WCN_DBG(FM_DBG | CHIP, "desen_rssi %d th:%d\n", rssi,mt6628_fm_config.rx_cfg.desene_rssi_th);
1644 // return value: 0, mcu dese disable; 1, enable; else error no
1645 static fm_s32 mt6628_mcu_dese(fm_u16 freq, void *arg)
1647 fm_mcu_desense_t state = FM_MCU_DESE_DISABLE;
1651 if (0 == fm_get_channel_space(freq)) {
1655 WCN_DBG(FM_DBG | CHIP, "%s, [freq=%d]\n", __func__, (int)freq);
1657 len = sizeof(mt6628_mcu_dese_list) / sizeof(mt6628_mcu_dese_list[0]);
1660 while ((indx < len) && (state != FM_MCU_DESE_ENABLE)) {
1661 if (mt6628_mcu_dese_list[indx] == freq) {
1662 state = FM_MCU_DESE_ENABLE;
1668 // request 6628 MCU change clk
1669 if (state == FM_MCU_DESE_DISABLE) {
1670 if (!mtk_wcn_wmt_dsns_ctrl(WMTDSNS_FM_DISABLE)) {
1675 if (!mtk_wcn_wmt_dsns_ctrl(WMTDSNS_FM_ENABLE)) {
1684 // return value: 0,mcu dese disable; 1, enable; else error no
1685 static fm_s32 mt6628_gps_dese(fm_u16 freq, void *arg)
1687 fm_gps_desense_t state = FM_GPS_DESE_DISABLE;
1691 if (0 == fm_get_channel_space(freq)) {
1695 WCN_DBG(FM_DBG | CHIP, "%s, [freq=%d]\n", __func__, (int)freq);
1697 len = sizeof(mt6628_gps_dese_list) / sizeof(mt6628_gps_dese_list[0]);
1700 while ((indx < len) && (state != FM_GPS_DESE_ENABLE)) {
1701 if (mt6628_gps_dese_list[indx] == freq) {
1702 state = FM_GPS_DESE_ENABLE;
1708 // request 6628 GPS change clk
1709 if (state == FM_GPS_DESE_DISABLE) {
1710 if (!mtk_wcn_wmt_dsns_ctrl(WMTDSNS_FM_GPS_DISABLE)) {
1715 if (!mtk_wcn_wmt_dsns_ctrl(WMTDSNS_FM_GPS_ENABLE)) {
1723 //get channel parameter, HL side/ FA / ATJ
1724 static fm_u16 mt6628_chan_para_get(fm_u16 freq)
1728 if (0 == fm_get_channel_space(freq)) {
1732 pos = (freq - 7600) / 5;
1734 size = sizeof(mt6628_chan_para_map) / sizeof(mt6628_chan_para_map[0]);
1736 pos = (pos < 0) ? 0 : pos;
1737 pos = (pos > (size - 1)) ? (size - 1) : pos;
1739 return mt6628_chan_para_map[pos];