MT6620: add the new driver JB2 V1.0
[firefly-linux-kernel-4.4.55.git] / drivers / mtk_wcn_combo / drv_fm / mt6628 / pub / mt6628_fm_lib.c
1 #include <linux/delay.h>
2 #include <linux/slab.h>
3 #include <linux/vmalloc.h>
4
5 #include "stp_exp.h"
6 #include "wmt_exp.h"
7
8 #include "fm_typedef.h"
9 #include "fm_dbg.h"
10 #include "fm_err.h"
11 #include "fm_interface.h"
12 #include "fm_stdlib.h"
13 #include "fm_patch.h"
14 #include "fm_utils.h"
15 #include "fm_link.h"
16 #include "fm_config.h"
17 #include "fm_private.h"
18
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;
27
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"
32
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},
39 };
40
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,
47 };
48
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
53 };
54
55 #define PATCH_SEG_LEN 512
56
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;
62
63 //static fm_bool rssi_th_set = fm_false;
64
65 #ifdef MT6628_FM_FPGA
66 #undef MT6628_FM_USE_6626EVB
67 #endif
68
69 #ifdef MTK_FM_50KHZ_SUPPORT
70 static struct fm_fifo *cqi_fifo = NULL;
71 #endif
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)
80 {
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");
84         return -FM_ELINK;
85     }else{
86         WCN_DBG(FM_ALT|CHIP,"WMT turn on LPBK OK!\n");
87         //return 0;
88     }*/
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");
91         return -FM_ELINK;
92     } else {
93         WCN_DBG(FM_ALT | CHIP, "WMT turn on FM OK!\n");
94         return 0;
95     }
96 }
97
98
99 static fm_s32 mt6628_pwroff(fm_s32 data)
100 {
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");
103         return -FM_ELINK;
104     } else {
105         WCN_DBG(FM_NTC | CHIP, "WMT turn off FM OK!\n");
106         return 0;
107     }
108 }
109
110 static fm_s32 Delayms(fm_u32 data)
111 {
112     WCN_DBG(FM_DBG | CHIP, "delay %dms\n", data);
113     msleep(data);
114     return 0;
115 }
116
117 static fm_s32 Delayus(fm_u32 data)
118 {
119     WCN_DBG(FM_DBG | CHIP, "delay %dus\n", data);
120     udelay(data);
121     return 0;
122 }
123
124 fm_s32 mt6628_get_read_result(struct fm_res_ctx* result)
125 {
126     FMR_ASSERT(result);
127     res = result;
128
129     return 0;
130 }
131
132 static fm_s32 mt6628_read(fm_u8 addr, fm_u16 *val)
133 {
134     fm_s32 ret = 0;
135     fm_u16 pkt_size;
136
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);
140
141     if (!ret && res) {
142         *val = res->fspi_rd;
143     }
144
145     FM_UNLOCK(cmd_buf_lock);
146
147     return ret;
148 }
149
150 static fm_s32 mt6628_write(fm_u8 addr, fm_u16 val)
151 {
152     fm_s32 ret = 0;
153     fm_u16 pkt_size;
154
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);
159
160     return ret;
161 }
162
163 static fm_s32 mt6628_set_bits(fm_u8 addr, fm_u16 bits, fm_u16 mask)
164 {
165     fm_s32 ret = 0;
166     fm_u16 val;
167
168     ret = mt6628_read(addr, &val);
169
170     if (ret)
171         return ret;
172
173     val = ((val & (mask)) | bits);
174     ret = mt6628_write(addr, val);
175
176     return ret;
177 }
178
179 static fm_u16 mt6628_get_chipid(void)
180 {
181     return 0x6628;
182 }
183
184 /*  MT6628_SetAntennaType - set Antenna type
185  *  @type - 1,Short Antenna;  0, Long Antenna
186  */
187 static fm_s32 mt6628_SetAntennaType(fm_s32 type)
188 {
189     fm_u16 dataRead;
190
191     WCN_DBG(FM_DBG | CHIP, "set ana to %s\n", type ? "short" : "long");
192     mt6628_read(FM_MAIN_CG2_CTRL, &dataRead);
193
194     if (type) {
195         dataRead |= ANTENNA_TYPE;
196     } else {
197         dataRead &= (~ANTENNA_TYPE);
198     }
199
200     mt6628_write(FM_MAIN_CG2_CTRL, dataRead);
201
202     return 0;
203 }
204
205 static fm_s32 mt6628_GetAntennaType(void)
206 {
207     fm_u16 dataRead;
208
209     mt6628_read(FM_MAIN_CG2_CTRL, &dataRead);
210     WCN_DBG(FM_DBG | CHIP, "get ana type: %s\n", (dataRead&ANTENNA_TYPE) ? "short" : "long");
211
212     if (dataRead&ANTENNA_TYPE)
213         return FM_ANA_SHORT; //short antenna
214     else
215         return FM_ANA_LONG; //long antenna
216 }
217
218
219 static fm_s32 mt6628_Mute(fm_bool mute)
220 {
221     fm_s32 ret = 0;
222     fm_u16 dataRead;
223
224     WCN_DBG(FM_DBG | CHIP, "set %s\n", mute ? "mute" : "unmute");
225     mt6628_read(FM_MAIN_CTRL, &dataRead);
226
227     if (mute == 1) {
228         ret = mt6628_write(FM_MAIN_CTRL, (dataRead&0xFFDF) | 0x0020);
229     } else {
230         ret = mt6628_write(FM_MAIN_CTRL, (dataRead&0xFFDF));
231 }
232
233     return ret;
234 }
235
236
237 /*static fm_s32 mt6628_set_RSSITh(fm_u16 TH_long, fm_u16 TH_short)
238 {
239     mt6628_write(0xE2, 0x3072);
240     mt6628_write(0xE3, TH_long);
241     mt6628_write(0xE1, 0x0002);
242     Delayms(1);
243     mt6628_write(0xE2, 0x307A);
244     mt6628_write(0xE3, TH_short);
245     mt6628_write(0xE1, 0x0002);
246
247     WCN_DBG(FM_DBG | CHIP, "RSSI TH, long:0x%04x, short:0x%04x", TH_long, TH_short);
248     return 0;
249 }
250 */
251 /*
252 static fm_s32 mt6628_set_SMGTh(fm_s32 ver, fm_u16 TH_smg)
253 {
254     if (mt6628_E1 == ver) {
255         mt6628_write(0xE2, 0x321E);
256         mt6628_write(0xE3, TH_smg);
257         mt6628_write(0xE1, 0x0002);
258     } else {
259         mt6628_write(0xE2, 0x3218);
260         mt6628_write(0xE3, TH_smg);
261         mt6628_write(0xE1, 0x0002);
262     }
263
264     WCN_DBG(FM_DBG | CHIP, "Soft-mute gain TH %d\n", (int)TH_smg);
265     return 0;
266 }
267 */
268 static fm_s32 mt6628_RampDown(void)
269 {
270     fm_s32 ret = 0;
271     fm_u16 pkt_size;
272     fm_u16 tmp;
273
274     WCN_DBG(FM_DBG | CHIP, "ramp down\n");
275
276     mt6628_read(FM_MAIN_INTRMASK, &tmp);
277     mt6628_write(FM_MAIN_INTRMASK, 0x0000);
278     mt6628_write(0x6B, 0x0000);
279
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);
284
285     if (ret) {
286         WCN_DBG(FM_ERR | CHIP, "ramp down failed\n");
287     }
288
289 #ifdef MT6628_FM_FPGA
290     Delayms(10);
291     mt6628_write(0x54, 0x0001);
292     mt6628_write(0x11, 0x37D4);
293     mt6628_write(0x54, 0x8000);
294 #endif
295     mt6628_write(0x6B, 0x2100);
296     mt6628_write(FM_MAIN_INTRMASK, tmp);
297     return ret;
298 }
299
300 static fm_s32 mt6628_get_rom_version(void)
301 {
302     fm_u16 tmp;
303
304     //DSP rom code version request enable --- set 0x61 b15=1
305     mt6628_set_bits(0x61, 0x8000, 0x7FFF);
306
307     //Release ASIP reset --- set 0x61 b1=1
308     mt6628_set_bits(0x61, 0x0002, 0xFFFD);
309
310     //Enable ASIP power --- set 0x61 b0=0
311     mt6628_set_bits(0x61, 0x0000, 0xFFFE);
312
313     //Wait DSP code version ready --- wait 1ms
314     Delayus(1000);
315
316     //Get FM DSP code version --- rd 0x83[15:8]
317     mt6628_read(0x83, &tmp);
318     tmp = (tmp >> 8);
319
320     //DSP rom code version request disable --- set 0x61 b15=0
321     mt6628_set_bits(0x61, 0x0000, 0x7FFF);
322
323     //Reset ASIP --- set 0x61[1:0] = 1
324     mt6628_set_bits(0x61, 0x0001, 0xFFFC);
325
326     WCN_DBG(FM_NTC | CHIP, "ROM version: v%d\n", (fm_s32)tmp);
327     return (fm_s32)tmp;
328 }
329
330 static fm_s32 mt6628_get_patch_path(fm_s32 ver, const fm_s8 **ppath)
331 {
332     fm_s32 i;
333     fm_s32 max = sizeof(mt6628_patch_tbl) / sizeof(mt6628_patch_tbl[0]);
334
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");
340             return 0;
341         }
342     }
343
344
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");
350             return 1;
351         }
352     }
353
354     // get path failed
355     WCN_DBG(FM_ERR | CHIP, "No valid patch file\n");
356     return -FM_EPATCH;
357 }
358
359
360 static fm_s32 mt6628_get_coeff_path(fm_s32 ver, const fm_s8 **ppath)
361 {
362     fm_s32 i;
363     fm_s32 max = sizeof(mt6628_patch_tbl) / sizeof(mt6628_patch_tbl[0]);
364
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");
370             return 0;
371         }
372     }
373
374
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");
380             return 1;
381         }
382     }
383
384     // get path failed
385     WCN_DBG(FM_ERR | CHIP, "No valid coeff file\n");
386     return -FM_EPATCH;
387 }
388
389
390 /*
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
395 */
396 static fm_s32 mt6628_DspPatch(const fm_u8 *img, fm_s32 len, enum IMG_TYPE type)
397 {
398     fm_u8 seg_num;
399     fm_u8 seg_id = 0;
400     fm_s32 seg_len;
401     fm_s32 ret = 0;
402     fm_u16 pkt_size;
403
404     FMR_ASSERT(img);
405
406     if (len <= 0) {
407         return -1;
408     }
409
410     seg_num = len / PATCH_SEG_LEN + 1;
411     WCN_DBG(FM_NTC | CHIP, "binary len:%d, seg num:%d\n", len, seg_num);
412
413     switch (type) {
414     case IMG_ROM:
415
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);
424
425             if (ret) {
426                 WCN_DBG(FM_ALT | CHIP, "mt6628_rom_download failed\n");
427                 return ret;
428             }
429         }
430
431         break;
432     case IMG_PATCH:
433
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);
442
443             if (ret) {
444                 WCN_DBG(FM_ALT | CHIP, "mt6628_patch_download failed\n");
445                 return ret;
446             }
447         }
448
449         break;
450     case IMG_HW_COEFFICIENT:
451
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);
460
461             if (ret) {
462                 WCN_DBG(FM_ALT | CHIP, "mt6628_hwcoeff_download failed\n");
463                 return ret;
464             }
465         }
466
467         break;
468     case IMG_COEFFICIENT:
469
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);
478
479             if (ret) {
480                 WCN_DBG(FM_ALT | CHIP, "mt6628_coeff_download failed\n");
481                 return ret;
482             }
483         }
484
485         break;
486     default:
487         break;
488     }
489
490     return 0;
491 }
492
493
494 static fm_s32 mt6628_PowerUp(fm_u16 *chip_id, fm_u16 *device_id)
495 {
496 #define PATCH_BUF_SIZE 4096*6
497     fm_s32 ret = 0;
498     fm_u16 pkt_size;
499     fm_u16 tmp_reg = 0;
500
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;
507
508     FMR_ASSERT(chip_id);
509     FMR_ASSERT(device_id);
510
511     WCN_DBG(FM_DBG | CHIP, "pwr on seq......\n");
512
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);
518
519     if (ret) {
520         WCN_DBG(FM_ALT | CHIP, "mt6628_pwrup_clock_on failed\n");
521         return ret;
522     }
523
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);
527 #endif
528
529     //Wholechip FM Power Up: step 2, read HW version
530     mt6628_read(0x62, &tmp_reg);
531     mt6628_read(0x62, &tmp_reg);
532     *chip_id = 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);
536
537     if (mt6628_hw_info.chip_id != 0x6628) {
538         WCN_DBG(FM_NTC | CHIP, "fm sys error, reset hw\n");
539         return (-FM_EFW);
540     }
541     
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;
545     
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);
550     } else {
551         WCN_DBG(FM_ERR | CHIP, "get ROM version failed\n");
552     }
553
554
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");
558         return -ENOMEM;
559     }
560
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);
564
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);
567
568     mt6628_hw_info.rom_ver += 1;
569     
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);
573     
574     if (ret == 1) {
575         dsp_buf[4] = 0x00;  //if we found rom version undefined, we should disable patch
576         dsp_buf[5] = 0x00;
577     }
578     
579     mt6628_DspPatch((const fm_u8*)dsp_buf, patch_len, IMG_COEFFICIENT);
580     mt6628_write(0x90, 0x0040);
581     mt6628_write(0x90, 0x0000);
582
583     if (dsp_buf) {
584         fm_vfree(dsp_buf);
585         dsp_buf = NULL;
586     }
587
588     //mt6628_check_dsp();
589     
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);
595     if (ret) {
596         WCN_DBG(FM_ALT | CHIP, "mt6628_pwrup_digital_init failed\n");
597         return ret;;
598     }
599
600     WCN_DBG(FM_NTC | CHIP, "pwr on seq ok\n");
601
602     //mt6628_check_dsp();
603
604 //    rssi_th_set = fm_false;
605     return ret;
606 }
607
608 static fm_s32 mt6628_PowerDown(void)
609 {
610     fm_s32 ret = 0;
611     fm_u16 pkt_size;
612     fm_u16 dataRead;
613
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.
618      */
619     mt6628_read(FM_MAIN_INTR, &dataRead);
620
621     if (dataRead & 0x1) {
622         mt6628_write(FM_MAIN_INTR, dataRead);//clear status flag
623     }
624
625     mt6628_RampDown();
626
627 #ifdef FM_DIGITAL_INPUT
628     mt6628_I2s_Setting(MT6628_I2S_OFF, MT6628_I2S_SLAVE, MT6628_I2S_44K);
629 #endif
630
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);
635
636     if (ret) {
637         WCN_DBG(FM_ALT | CHIP, "mt6628_pwrdown failed\n");
638         return ret;
639     }
640
641     //FIX_ME, disable ext interrupt
642     mt6628_write(FM_MAIN_EXTINTRMASK, 0x00);
643
644 //    rssi_th_set = fm_false;
645     return ret;
646 }
647
648 static fm_bool mt6628_SetFreq(fm_u16 freq)
649 {
650     fm_s32 ret = 0;
651     fm_u16 pkt_size;
652     fm_u16 chan_para = 0;
653
654     fm_cb_op->cur_freq_set(freq);
655
656
657     //MCU clock adjust if need
658     if ((ret = mt6628_mcu_dese(freq, NULL)) < 0)
659         {
660                 WCN_DBG(FM_ERR | MAIN, "mt6628_mcu_dese FAIL:%d\n", ret);
661     }
662
663     WCN_DBG(FM_INF | MAIN, "MCU %d\n", ret);
664
665     //GPS clock adjust if need
666     if ((ret = mt6628_gps_dese(freq, NULL)) < 0) 
667         {
668                 WCN_DBG(FM_ERR | MAIN, "mt6628_gps_dese FAIL:%d\n", ret);
669     }
670
671     WCN_DBG(FM_INF | MAIN, "GPS %d\n", ret);
672     //start tune
673     if (FM_LOCK(cmd_buf_lock)) return fm_false;
674
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);
678 //    }
679
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);
683
684     if (ret) {
685         WCN_DBG(FM_ALT | CHIP, "mt6628_tune failed\n");
686         return ret;
687     }
688
689     WCN_DBG(FM_DBG | CHIP, "set freq to %d ok\n", freq);
690
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;
695     }*/
696
697     return fm_true;
698 }
699
700
701 /*
702 * mt6628_Seek
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
707 */
708 static fm_bool mt6628_Seek(fm_u16 min_freq, fm_u16 max_freq, fm_u16 *pFreq, fm_u16 seekdir, fm_u16 space)
709 {
710     fm_s32 ret = 0;
711     fm_u16 pkt_size,temp;
712
713     mt6628_RampDown();
714     mt6628_read(FM_MAIN_CTRL, &temp);
715     mt6628_Mute(fm_true);
716
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);
721
722     if (!ret && res) {
723         *pFreq = res->seek_result;
724         //fm_cb_op->cur_freq_set(*pFreq);
725     } else {
726         WCN_DBG(FM_ALT | CHIP, "mt6628_seek failed\n");
727         return ret;
728     }
729
730     //get the result freq
731     WCN_DBG(FM_NTC | CHIP, "seek, result freq:%d\n", *pFreq);
732     mt6628_RampDown();
733         if((temp&0x0020) == 0)
734         {
735             mt6628_Mute(fm_false);
736         }
737
738     return fm_true;
739 }
740
741 #define FM_CQI_LOG_PATH "/mnt/sdcard/fmcqilog"
742
743 static fm_s32 mt6628_full_cqi_get(fm_s32 min_freq, fm_s32 max_freq, fm_s32 space, fm_s32 cnt)
744 {
745     fm_s32 ret = 0;
746     fm_u16 pkt_size;
747     fm_u16 freq, orig_freq;
748     fm_s32 i, j, k;
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};
753     fm_s32 pos;
754     fm_u8 cqi_log_path[100] = {0};
755     
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)) {
760         freq *= 10;
761     }
762     // get cqi
763     orig_freq = freq;
764         if (0 == fm_get_channel_space(min_freq)) {
765                 min = min_freq * 10;
766         } else {
767                 min = min_freq;
768         }
769         if (0 == fm_get_channel_space(max_freq)) {
770                 max = max_freq * 10;
771         } else {
772                 max = max_freq;
773         }
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
780         } else {
781                 space_val = 10;
782         }
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++)
785     {
786                 WCN_DBG(FM_NTC | CHIP, "cqi file:%d\n", k+1);
787         freq = min;
788         pos = 0;
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++) 
793         {
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);
798             
799             if (!ret && res) {
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++) {
803                     // just for debug
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", 
805                         p_cqi[i].ch, 
806                         p_cqi[i].rssi,
807                         p_cqi[i].pamd,
808                         p_cqi[i].pr,
809                         p_cqi[i].fpamd,
810                         p_cqi[i].mr,
811                         p_cqi[i].atdc,
812                         p_cqi[i].prx,
813                         p_cqi[i].atdev,
814                         p_cqi[i].smg,
815                         p_cqi[i].drssi); 
816                     // format to buffer
817                     sprintf(cqi_log_buf, "%04d,%04x,%04x,%04x,%04x,%04x,%04x,%04x,%04x,%04x,%04x,\n", 
818                         p_cqi[i].ch, 
819                         p_cqi[i].rssi,
820                         p_cqi[i].pamd,
821                         p_cqi[i].pr,
822                         p_cqi[i].fpamd,
823                         p_cqi[i].mr,
824                         p_cqi[i].atdc,
825                         p_cqi[i].prx,
826                         p_cqi[i].atdev,
827                         p_cqi[i].smg,
828                         p_cqi[i].drssi); 
829                     // write back to log file
830                     fm_file_write(cqi_log_path, cqi_log_buf, strlen(cqi_log_buf), &pos);
831                 }
832             } 
833             else 
834             {
835                 WCN_DBG(FM_ALT | CHIP, "smt get CQI failed\n");
836                 ret = -1;
837             }
838             freq += space_val;
839         }
840         fm_cb_op->cur_freq_set(0);//avoid run too much times
841     }
842         WCN_DBG(FM_NTC | CHIP, "6628 cqi log done\n");
843
844     return ret;
845 }
846
847
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)
850 {
851     fm_s32 ret = 0;
852     fm_u16 pkt_size,temp;
853     fm_u16 offset = 0;
854     fm_u16 tmp_scanTBLsize = *ScanTBLsize;
855
856     if ((!pScanTBL) || (tmp_scanTBLsize == 0)) {
857         WCN_DBG(FM_ALT | CHIP, "scan, failed:invalid scan table\n");
858         return fm_false;
859     }
860
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);
862
863     mt6628_RampDown();
864     mt6628_read(FM_MAIN_CTRL, &temp);
865     mt6628_Mute(fm_true);
866
867     mt6628_full_cqi_get(min_freq, max_freq, space, 5);
868     
869     // normal scan
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);
874
875     if (!ret && res) {
876         fm_memcpy(pScanTBL, res->scan_result, sizeof(fm_u16)*FM_SCANTBL_SIZE);
877         WCN_DBG(FM_NTC | CHIP, "Rx scan result:\n");
878
879         for (offset = 0; offset < tmp_scanTBLsize; offset++) {
880             WCN_DBG(FM_NTC | CHIP, "%d: %04x\n", (fm_s32)offset, *(pScanTBL + offset));
881         }
882
883         *ScanTBLsize = tmp_scanTBLsize;
884     } else {
885         WCN_DBG(FM_ALT | CHIP, "mt6628_scan failed\n");
886         return ret;
887     }
888
889     mt6628_set_bits(FM_MAIN_CTRL, 0x0000, 0xFFF0); //make sure tune/seek/scan/cqi bits = 0
890         if((temp&0x0020) == 0)
891         {
892                 mt6628_Mute(fm_false);
893         }
894
895     return fm_true;
896 }
897
898 //add for scan cancel case
899 static fm_bool cqi_abort = fm_false;
900
901 static fm_s32 mt6628_CQI_Get(fm_s8 *buf, fm_s32 buf_len)
902 {
903     fm_s32 ret = 0;
904     fm_s32 i;
905     fm_u16 pkt_size;
906     struct mt6628_fm_cqi *pmt6628_cqi;
907     struct adapt_fm_cqi  *pcqi;
908
909     if (!buf || buf_len < FM_CQI_BUF_SIZE) {
910         return -FM_EBUF;
911     }
912
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;
917         ret = -1;
918     } else {
919         ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_SCAN | FLAG_CQI_DONE, SW_RETRY_CNT, SCAN_TIMEOUT, mt6628_get_read_result);
920     }
921     FM_UNLOCK(cmd_buf_lock);
922
923     if (!ret && res) {
924         //FIXEDME
925         pmt6628_cqi = (struct mt6628_fm_cqi*)res->cqi;
926         pcqi = (struct adapt_fm_cqi*)buf;
927
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;
931
932             if (pcqi[i].rssi >= 32768) {
933                 pcqi[i].rssi = pcqi[i].rssi - 65536;
934             }
935
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);
938         }
939     } else {
940         WCN_DBG(FM_ALT | CHIP, "mt6628 get CQI failed:%d\n",ret);
941     }
942
943     mt6628_set_bits(FM_MAIN_CTRL, 0x0000, 0xFFF0); //make sure tune/seek/scan/cqi bits = 0
944
945     return ret;
946 }
947
948 static fm_bool scan_abort = fm_false;
949
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};
953
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)
956 {
957     fm_s32 ret = 0;
958     fm_s32 num;
959     fm_s32 seg;
960     fm_s32 i, j;
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;
964     fm_s32 chl_cnt = 0;
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;
968
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
975     }
976     
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
980
981     FM_FIFO_RESET(cqi_fifo);
982     fm_memset(pScanTBL, 0, sizeof(fm_u16) * (*ScanTBLsize));
983     
984     // do scan
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;
990         chl_cnt = 0;
991
992         if (fm_true == scan_abort) {
993             scan_abort = fm_false;
994             return fm_false;
995         }
996         
997         if (fm_false == mt6628_Scan(start_freq, end_freq, pFreq, scan_tbl, ScanTBLsize, scandir, space)) {
998             return fm_false;
999         }
1000
1001         // get channel count
1002         for (ch_offset = 0; ch_offset < FM_SCANTBL_SIZE; ch_offset++) {
1003                     if (scan_tbl[ch_offset] == 0)
1004                             continue;
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) {
1010                         chl_cnt++; 
1011                         // set reult bitmap
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);
1016                         }
1017                         WCN_DBG(FM_NTC | CHIP, "cnt %d, word %d, bit %d\n", chl_cnt, word_offset, bit_offset);
1018                     }
1019                             }
1020                     }
1021             }
1022
1023         // get cqi info
1024         while (chl_cnt > 0) {
1025             ret = mt6628_CQI_Get(raw_buf, 16 * sizeof(struct adapt_fm_cqi));
1026             if (ret) {
1027                 return ret;
1028             }
1029
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);
1035             }
1036         }
1037             
1038             chl_cnt -= 16;
1039         }
1040     }
1041     
1042     return fm_true;
1043 }
1044
1045
1046 static fm_s32 mt6628_CQI_Get_50KHz(fm_s8 *buf, fm_s32 buf_len)
1047 {
1048     fm_s32 ret = 0;
1049     fm_s32 i;
1050     struct adapt_fm_cqi tmp = {
1051         .ch = 0,
1052         .rssi = 0,
1053     };
1054     struct adapt_fm_cqi *pcqi = (struct adapt_fm_cqi *)buf;
1055
1056     
1057     if (!buf || buf_len < FM_CQI_BUF_SIZE) {
1058         return -FM_EBUF;
1059     }
1060
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);
1067     }
1068     
1069     return ret;
1070 }
1071
1072 #endif //MTK_FM_50KHZ_SUPPORT
1073
1074
1075 /*
1076  * mt6628_GetCurRSSI - get current freq's RSSI value
1077  * RS=RSSI
1078  * If RS>511, then RSSI(dBm)= (RS-1024)/16*6
1079  *                                 else RSSI(dBm)= RS/16*6
1080  */
1081 static fm_s32 mt6628_GetCurRSSI(fm_s32 *pRSSI)
1082 {
1083     fm_u16 tmp_reg;
1084
1085     mt6628_read(FM_RSSI_IND, &tmp_reg);
1086     tmp_reg = tmp_reg & 0x03ff;
1087
1088     if (pRSSI) {
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);
1091     } else {
1092         WCN_DBG(FM_ERR | CHIP, "get rssi para error\n");
1093         return -FM_EPARA;
1094     }
1095
1096     return 0;
1097 }
1098
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
1104 };
1105 static fm_s32 mt6628_SetVol(fm_u8 vol)
1106 {
1107     fm_s32 ret = 0;
1108     
1109     vol = (vol > 15) ? 15 : vol;
1110     ret = mt6628_write(0x7D, mt6628_vol_tbl[vol]); 
1111     if (ret) {
1112         WCN_DBG(FM_ERR | CHIP, "Set vol=%d Failed\n", vol);
1113         return ret;
1114     } else {
1115         WCN_DBG(FM_DBG | CHIP, "Set vol=%d OK\n", vol);
1116     }
1117
1118     if (vol == 10) {
1119         fm_print_cmd_fifo();    //just for debug
1120         fm_print_evt_fifo();
1121     }
1122     return 0;
1123 }
1124
1125 static fm_s32 mt6628_GetVol(fm_u8 *pVol)
1126 {
1127     int ret = 0;
1128     fm_u16 tmp;
1129     fm_s32 i;
1130
1131     FMR_ASSERT(pVol);
1132
1133     ret = mt6628_read(0x7D, &tmp);
1134     if (ret) {
1135         *pVol = 0;
1136         WCN_DBG(FM_ERR | CHIP, "Get vol Failed\n");
1137         return ret;
1138     } 
1139
1140     for (i = 0; i < 16; i++) {
1141         if (mt6628_vol_tbl[i] == tmp) {
1142             *pVol = i;
1143             break;
1144         }
1145     }
1146
1147     WCN_DBG(FM_DBG | CHIP, "Get vol=%d OK\n", *pVol);
1148     return 0;
1149 }
1150
1151 static fm_s32 mt6628_dump_reg(void)
1152 {
1153         fm_s32 i;
1154     fm_u16 TmpReg;
1155         for(i=0; i<0xff; i++)
1156         {
1157         mt6628_read(i, &TmpReg);
1158                 WCN_DBG(FM_NTC | CHIP, "0x%02x=0x%04x\n",i,TmpReg);
1159         }
1160     return 0;
1161 }
1162
1163 static fm_bool mt6628_GetMonoStereo(fm_u16 *pMonoStereo)
1164 {
1165 #define FM_BF_STEREO 0x1000
1166     fm_u16 TmpReg;
1167
1168     if (pMonoStereo) {
1169         mt6628_read(FM_RSSI_IND, &TmpReg);
1170         *pMonoStereo = (TmpReg & FM_BF_STEREO) >> 12;
1171     } else {
1172         WCN_DBG(FM_ERR | CHIP, "MonoStero: para err\n");
1173         return fm_false;
1174     }
1175
1176     WCN_DBG(FM_DBG | CHIP, "MonoStero:0x%04x\n", *pMonoStereo);
1177     return fm_true;
1178 }
1179
1180 static fm_s32 mt6628_SetMonoStereo(fm_s32 MonoStereo)
1181 {
1182     fm_s32 ret = 0;
1183 #define FM_FORCE_MS 0x0008
1184
1185     WCN_DBG(FM_DBG | CHIP, "set to %s\n", MonoStereo ? "mono" : "auto");
1186
1187     mt6628_write(0x60, 0x3007);
1188
1189     if (MonoStereo) {
1190         ret = mt6628_set_bits(0x75, FM_FORCE_MS, ~FM_FORCE_MS);
1191     } else {
1192         ret = mt6628_set_bits(0x75, 0x0000, ~FM_FORCE_MS);
1193     }
1194
1195     return ret;
1196 }
1197
1198 static fm_s32 mt6628_GetCapArray(fm_s32 *ca)
1199 {
1200     fm_u16 dataRead;
1201     fm_u16 tmp = 0;
1202
1203     FMR_ASSERT(ca);
1204     mt6628_read(0x60, &tmp);
1205     mt6628_write(0x60, tmp&0xFFF7); //0x60 D3=0
1206
1207     mt6628_read(0x26, &dataRead);
1208     *ca = dataRead;
1209
1210     mt6628_write(0x60, tmp); //0x60 D3=1
1211     return 0;
1212 }
1213
1214 /*
1215  * mt6628_GetCurPamd - get current freq's PAMD value
1216  * PA=PAMD
1217  * If PA>511 then PAMD(dB)=  (PA-1024)/16*6,
1218  *                              else PAMD(dB)=PA/16*6
1219  */
1220 static fm_bool mt6628_GetCurPamd(fm_u16 *pPamdLevl)
1221 {
1222     fm_u16 tmp_reg;
1223     fm_u16 dBvalue,valid_cnt=0;
1224         int i,total=0;
1225     for (i = 0; i < 8; i++) 
1226         {
1227             if (mt6628_read(FM_ADDR_PAMD, &tmp_reg))
1228             {
1229                 *pPamdLevl = 0;
1230                 return fm_false;
1231             }
1232
1233             tmp_reg &= 0x03FF;
1234             dBvalue = (tmp_reg > 256) ? ((512 - tmp_reg) * 6 / 16) : 0;
1235                 if(dBvalue != 0)
1236                 {
1237                         total += dBvalue;
1238                         valid_cnt++;
1239                         WCN_DBG(FM_DBG | CHIP, "[%d]PAMD=%d\n",i,dBvalue);
1240                 }
1241                 Delayms(3);
1242         }
1243         if(valid_cnt != 0)
1244         {
1245             *pPamdLevl = total/valid_cnt;
1246         }
1247         else
1248         {
1249                 *pPamdLevl = 0;
1250         }
1251     WCN_DBG(FM_NTC | CHIP, "PAMD=%d\n", *pPamdLevl);
1252     return fm_true;
1253 }
1254
1255 static fm_s32 mt6628_ScanStop(void)
1256 {
1257     cqi_abort = fm_true;
1258     scan_abort = fm_true;
1259     fm_force_active_event(FLAG_SCAN_DONE | FLAG_CQI_DONE);
1260     
1261     return 0;
1262 }
1263
1264 static fm_s32 mt6628_SeekStop(void)
1265 {
1266     return fm_force_active_event(FLAG_SEEK_DONE);
1267 }
1268
1269
1270 /*
1271  * mt6628_I2s_Setting - set the I2S state on MT6628
1272  * @onoff - I2S on/off
1273  * @mode - I2S mode: Master or Slave
1274  *
1275  * Return:0, if success; error code, if failed
1276  */
1277 static fm_s32 mt6628_I2s_Setting(fm_s32 onoff, fm_s32 mode, fm_s32 sample)
1278 {
1279     fm_u16 tmp_state = 0;
1280     fm_u16 tmp_mode = 0;
1281     fm_u16 tmp_sample = 0;
1282     fm_s32 ret = 0;
1283
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;
1290     } else {
1291         WCN_DBG(FM_ERR | CHIP, "%s():[onoff=%d]\n", __func__, onoff);
1292         ret = -FM_EPARA;
1293         goto out;
1294     }
1295
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;
1302     } else {
1303         WCN_DBG(FM_ERR | CHIP, "%s():[mode=%d]\n", __func__, mode);
1304         ret = -FM_EPARA;
1305         goto out;
1306     }
1307
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;
1317     } else {
1318         WCN_DBG(FM_ERR | CHIP, "%s():[sample=%d]\n", __func__, sample);
1319         ret = -FM_EPARA;
1320         goto out;
1321     }
1322
1323     if ((ret = mt6628_set_bits(0x5F, tmp_sample, 0xE7FF)))
1324         goto out;
1325
1326     if ((ret = mt6628_set_bits(0x9B, tmp_mode, 0xFFF7)))
1327         goto out;
1328
1329     if ((ret = mt6628_set_bits(0x61, tmp_state, 0xFF7F)))
1330         goto out;
1331
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",
1335             sample);
1336 out:
1337     return ret;
1338 }
1339
1340
1341
1342 static fm_s32 mt6628_i2s_info_get(fm_s32 *ponoff, fm_s32 *pmode, fm_s32 *psample)
1343 {
1344     FMR_ASSERT(ponoff);
1345     FMR_ASSERT(pmode);
1346     FMR_ASSERT(psample);
1347
1348     *ponoff = mt6628_i2s_inf.status;
1349     *pmode = mt6628_i2s_inf.mode;
1350     *psample = mt6628_i2s_inf.rate;
1351
1352     return 0;
1353 }
1354
1355
1356 static fm_s32 mt6628_hw_info_get(struct fm_hw_info *req)
1357 {
1358     FMR_ASSERT(req);
1359
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;
1364
1365     return 0;
1366 }
1367
1368 static fm_s32 mt6628_soft_mute_tune(fm_u16 freq,fm_s32 *rssi,fm_bool *valid)
1369 {
1370     fm_s32 ret=0;
1371     fm_u16 pkt_size;
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;
1377     
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);
1382         
1383         if (!ret && res) 
1384         {
1385                 WCN_DBG(FM_NTC | CHIP, "smt cqi size %d\n", res->cqi[0]);
1386                 p_cqi = (struct mt6628_full_cqi*)&res->cqi[2];
1387                 // just for debug
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", 
1389                         p_cqi->ch, 
1390                         p_cqi->rssi,
1391                         p_cqi->pamd,
1392                         p_cqi->pr,
1393                         p_cqi->fpamd,
1394                         p_cqi->mr,
1395                         p_cqi->atdc,
1396                         p_cqi->prx,
1397                         p_cqi->atdev,
1398                         p_cqi->smg,
1399                         p_cqi->drssi); 
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);
1404                 if(ATDC < 0)
1405                 {
1406                         ATDC = (~(ATDC)) - 1;//Get abs value of ATDC
1407                 }
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))
1419                 {        
1420                         *valid = fm_true;
1421                 }
1422                 else
1423                 {
1424                         *valid = fm_false;
1425                 }
1426                 *rssi = RSSI;
1427 /*              if(RSSI < -296) 
1428                         WCN_DBG(FM_NTC | CHIP, "rssi\n");
1429                 else if(PAMD > -12) 
1430                         WCN_DBG(FM_NTC | CHIP, "PAMD\n");
1431                 else if(ATDC > 3496) 
1432                         WCN_DBG(FM_NTC | CHIP, "ATDC\n");
1433                 else if(MR < -67) 
1434                         WCN_DBG(FM_NTC | CHIP, "MR\n");
1435                 else if(PRX < 80) 
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");
1441                         */
1442         }
1443         else 
1444         {
1445                 WCN_DBG(FM_ALT | CHIP, "smt get CQI failed\n");
1446                 return fm_false;
1447         }
1448         WCN_DBG(FM_NTC | CHIP, "valid=%d\n",*valid);
1449         return fm_true;
1450 }
1451
1452 static fm_bool mt6628_em_test(fm_u16 group_idx, fm_u16 item_idx, fm_u32 item_value)
1453 {
1454     return fm_true;
1455 }
1456
1457 static fm_s32 MT6628fm_low_power_wa_default(fm_s32 fmon)
1458 {
1459     return 0;
1460 }
1461
1462 fm_s32 MT6628fm_low_ops_register(struct fm_lowlevel_ops *ops)
1463 {
1464     fm_s32 ret = 0;
1465     //Basic functions.
1466
1467     FMR_ASSERT(ops);
1468     FMR_ASSERT(ops->cb.cur_freq_get);
1469     FMR_ASSERT(ops->cb.cur_freq_set);
1470     fm_cb_op = &ops->cb;
1471
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;
1493     #endif
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;
1513
1514     cmd_buf_lock = fm_lock_create("28_cmd");
1515     ret = fm_lock_get(cmd_buf_lock);
1516
1517     cmd_buf = fm_zalloc(TX_BUF_SIZE + 1);
1518
1519     if (!cmd_buf) {
1520         WCN_DBG(FM_ALT | CHIP, "6628 fm lib alloc tx buf failed\n");
1521         ret = -1;
1522     }
1523
1524 #ifdef MTK_FM_50KHZ_SUPPORT
1525     cqi_fifo = fm_fifo_create("6628_cqi_fifo", sizeof(struct adapt_fm_cqi), 640);
1526     if (!cqi_fifo) {
1527         WCN_DBG(FM_ALT | CHIP, "6628 fm lib create cqi fifo failed\n");
1528         ret = -1;
1529     }
1530 #endif
1531
1532     return ret;
1533 }
1534
1535 fm_s32 MT6628fm_low_ops_unregister(struct fm_lowlevel_ops *ops)
1536 {
1537     fm_s32 ret = 0;
1538     //Basic functions.
1539     FMR_ASSERT(ops);
1540
1541 #ifdef MTK_FM_50KHZ_SUPPORT
1542     fm_fifo_release(cqi_fifo);
1543 #endif
1544
1545     if (cmd_buf) {
1546         fm_free(cmd_buf);
1547         cmd_buf = NULL;
1548     }
1549
1550     ret = fm_lock_put(cmd_buf_lock);
1551     fm_memset(&ops->bi, 0, sizeof(struct fm_basic_interface));
1552     return ret;
1553 }
1554 //static struct fm_pub pub;
1555 //static struct fm_pub_cb *pub_cb = &pub.pub_tbl;
1556
1557 static const fm_u16 mt6628_mcu_dese_list[] = {
1558         7630, 7800, 7940, 8320, 9260, 9600, 9710, 9920, 10400, 10410
1559 };
1560
1561 static const fm_u16 mt6628_gps_dese_list[] = {
1562         7850, 7860
1563 };
1564
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
1598         0   //10800
1599 };
1600
1601
1602 static const fm_u16 mt6628_scan_dese_list[] = {
1603         7680, 8210, 8450, 9210, 9220, 9600, 9840, 10400, 10750, 10760
1604 };
1605
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)
1608 {
1609     fm_s32 size;
1610
1611     size = sizeof(mt6628_scan_dese_list) / sizeof(mt6628_scan_dese_list[0]);
1612
1613     if (0 == fm_get_channel_space(freq)) {
1614         freq *= 10;
1615     }
1616     
1617     while (size) {
1618         if (mt6628_scan_dese_list[size -1] == freq)
1619             return 1;
1620
1621         size--;
1622     }
1623
1624     return 0;
1625 }
1626
1627 /*  return value:
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)
1631 {
1632         if(mt6628_is_dese_chan(freq))
1633         {
1634                 if(rssi<mt6628_fm_config.rx_cfg.desene_rssi_th)
1635                 {
1636                         return 1;
1637                 }
1638                 WCN_DBG(FM_DBG | CHIP, "desen_rssi %d th:%d\n", rssi,mt6628_fm_config.rx_cfg.desene_rssi_th);
1639         }
1640     return 0;
1641 }
1642
1643
1644 // return value: 0, mcu dese disable; 1, enable; else error no
1645 static fm_s32 mt6628_mcu_dese(fm_u16 freq, void *arg)
1646 {
1647     fm_mcu_desense_t state = FM_MCU_DESE_DISABLE;
1648     fm_s32 len = 0;
1649     fm_s32 indx = 0;
1650
1651     if (0 == fm_get_channel_space(freq)) {
1652         freq *= 10;
1653     }
1654     
1655     WCN_DBG(FM_DBG | CHIP, "%s, [freq=%d]\n", __func__, (int)freq);
1656
1657     len = sizeof(mt6628_mcu_dese_list) / sizeof(mt6628_mcu_dese_list[0]);
1658     indx = 0;
1659
1660     while ((indx < len) && (state != FM_MCU_DESE_ENABLE)) {
1661         if (mt6628_mcu_dese_list[indx] == freq) {
1662             state = FM_MCU_DESE_ENABLE;
1663         }
1664
1665         indx++;
1666     }
1667
1668     // request 6628 MCU change clk
1669     if (state == FM_MCU_DESE_DISABLE) {
1670         if (!mtk_wcn_wmt_dsns_ctrl(WMTDSNS_FM_DISABLE)) {
1671             return -1;
1672         }
1673         return 0;
1674     } else {
1675         if (!mtk_wcn_wmt_dsns_ctrl(WMTDSNS_FM_ENABLE)) {
1676             return -1;
1677         }
1678         return 1;
1679     }
1680 }
1681
1682
1683
1684 // return value: 0,mcu dese disable; 1, enable; else error no
1685 static fm_s32 mt6628_gps_dese(fm_u16 freq, void *arg)
1686 {
1687     fm_gps_desense_t state = FM_GPS_DESE_DISABLE;
1688     fm_s32 len = 0;
1689     fm_s32 indx = 0;
1690
1691     if (0 == fm_get_channel_space(freq)) {
1692         freq *= 10;
1693     }
1694     
1695     WCN_DBG(FM_DBG | CHIP, "%s, [freq=%d]\n", __func__, (int)freq);
1696
1697     len = sizeof(mt6628_gps_dese_list) / sizeof(mt6628_gps_dese_list[0]);
1698     indx = 0;
1699
1700     while ((indx < len) && (state != FM_GPS_DESE_ENABLE)) {
1701         if (mt6628_gps_dese_list[indx] == freq) {
1702             state = FM_GPS_DESE_ENABLE;
1703         }
1704
1705         indx++;
1706     }
1707
1708     // request 6628 GPS change clk
1709     if (state == FM_GPS_DESE_DISABLE) {
1710         if  (!mtk_wcn_wmt_dsns_ctrl(WMTDSNS_FM_GPS_DISABLE))  {
1711             return -1;
1712         }
1713         return 0;
1714     } else {
1715         if (!mtk_wcn_wmt_dsns_ctrl(WMTDSNS_FM_GPS_ENABLE)) {
1716             return -1;
1717         }
1718         return 1;
1719     }
1720 }
1721
1722
1723 //get channel parameter, HL side/ FA / ATJ
1724 static fm_u16 mt6628_chan_para_get(fm_u16 freq)
1725 {
1726     fm_s32 pos, size;
1727
1728     if (0 == fm_get_channel_space(freq)) {
1729         freq *= 10;
1730     }
1731
1732     pos = (freq - 7600) / 5;
1733     
1734     size = sizeof(mt6628_chan_para_map) / sizeof(mt6628_chan_para_map[0]);
1735
1736     pos = (pos < 0) ? 0 : pos;
1737     pos = (pos > (size - 1)) ? (size - 1) : pos;
1738
1739     return mt6628_chan_para_map[pos];
1740 }
1741