MT6620: add the new driver JB2 V1.0
[firefly-linux-kernel-4.4.55.git] / drivers / mtk_wcn_combo / drv_fm / core / fm_main.c
1 /* fm_main.c
2  *
3  * (C) Copyright 2011
4  * MediaTek <www.MediaTek.com>
5  * Hongcheng <hongcheng.xia@MediaTek.com>
6  *
7  * FM Radio Driver -- main functions
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 #include <linux/kernel.h>
24 #include <asm/uaccess.h>
25 #include <linux/slab.h>
26
27 #include "fm_main.h"
28 #include "fm_config.h"
29 //#include "fm_cust_cfg.h"
30 #include "wmt_exp.h"
31 //fm main data structure
32 static struct fm *g_fm_struct = NULL;
33 //we must get low level interface first, when add a new chip, the main effort is this interface
34 static struct fm_lowlevel_ops fm_low_ops;
35 #ifdef MT6620_FM
36 static struct fm_lowlevel_ops MT6620fm_low_ops;
37 #endif
38 #ifdef MT6628_FM
39 static struct fm_lowlevel_ops MT6628fm_low_ops;
40 #endif
41 //MTK FM Radio private advanced features
42 #if 0//(!defined(MT6620_FM)&&!defined(MT6628_FM))
43 static struct fm_priv priv_adv;
44 #endif
45 //mutex for char device ops
46 static struct fm_lock *fm_ops_lock;
47 //mutex for RDS parsing and read result
48 static struct fm_lock *fm_read_lock;
49 //for get rds block counter
50 static struct fm_lock *fm_rds_cnt;
51 //mutex for fm timer, RDS reset
52 static struct fm_lock *fm_timer_lock;
53 static struct fm_lock *fm_rxtx_lock;//protect FM RX TX mode switch 
54 static struct fm_lock *fm_rtc_mutex;//protect FM GPS RTC drift info  
55
56 static struct fm_timer *fm_timer_sys;
57
58 static struct fm_i2s_info fm_i2s_inf = {
59     .status = 0,    //i2s off
60     .mode = 0,      //slave mode
61     .rate = 48000,  //48000 sample rate
62 };
63
64 static fm_bool scan_stop_flag = fm_false;
65 static struct fm_gps_rtc_info gps_rtc_info;
66
67 //RDS reset related functions
68 static fm_u16 fm_cur_freq_get(void);
69 static fm_s32 fm_cur_freq_set(fm_u16 new_freq);
70 static enum fm_op_state fm_op_state_get(struct fm *fmp);
71 static enum fm_op_state fm_op_state_set(struct fm *fmp, enum fm_op_state sta);
72 static void fm_timer_func(unsigned long data);
73 static void fmtx_timer_func(unsigned long data);
74
75 static void fm_enable_rds_BlerCheck(struct fm *fm);
76 static void fm_disable_rds_BlerCheck(void);
77 static void fm_rds_reset_work_func(unsigned long data);
78 //when interrupt be triggered by FM chip, fm_eint_handler will first be executed
79 //then fm_eint_handler will schedule fm_eint_work_func to run
80 static void fm_eint_handler(void);
81 static void fm_eint_work_func(unsigned long data);
82 static fm_s32 fm_rds_parser(struct rds_rx_t *rds_raw, fm_s32 rds_size);
83 static fm_s32 fm_callback_register(struct fm_lowlevel_ops *ops);
84 static fm_s32 fm_callback_unregister(struct fm_lowlevel_ops *ops);
85
86 static fm_s32 pwrdown_flow(struct fm *fm);
87
88 static  fm_u16 fm_cur_freq_get(void)
89 {
90     return g_fm_struct ? g_fm_struct->cur_freq : 0;
91 }
92
93 static  fm_s32 fm_cur_freq_set(fm_u16 new_freq)
94 {
95     if (g_fm_struct)
96         g_fm_struct->cur_freq = new_freq;
97
98     return 0;
99 }
100
101 static enum fm_op_state fm_op_state_get(struct fm *fmp)
102 {
103     if (fmp) {
104         WCN_DBG(FM_DBG | MAIN, "op state get %d\n", fmp->op_sta);
105         return fmp->op_sta;
106     } else {
107         WCN_DBG(FM_ERR | MAIN, "op state get para error\n");
108         return FM_STA_UNKOWN;
109     }
110 }
111
112 static enum fm_op_state fm_op_state_set(struct fm *fmp, enum fm_op_state sta)
113 {
114     if (fmp && (sta < FM_STA_MAX)) {
115         fmp->op_sta = sta;
116         WCN_DBG(FM_DBG | MAIN, "op state set to %d\n", sta);
117         return fmp->op_sta;
118     } else {
119         WCN_DBG(FM_ERR | MAIN, "op state set para error, %d\n", sta);
120         return FM_STA_UNKOWN;
121     }
122 }
123
124 enum fm_pwr_state fm_pwr_state_get(struct fm *fmp)
125 {
126     if (fmp) {
127         WCN_DBG(FM_DBG | MAIN, "pwr state get %d\n", fmp->pwr_sta);
128         return fmp->pwr_sta;
129     } else {
130         WCN_DBG(FM_ERR | MAIN, "pwr state get para error\n");
131         return FM_PWR_MAX;
132     }
133 }
134
135 enum fm_pwr_state fm_pwr_state_set(struct fm *fmp, enum fm_pwr_state sta)
136 {
137     if (fmp && (sta < FM_PWR_MAX)) {
138         fmp->pwr_sta = sta;
139         WCN_DBG(FM_NTC | MAIN, "pwr state set to %d\n", sta);
140         return fmp->pwr_sta;
141     } else {
142         WCN_DBG(FM_ERR | MAIN, "pwr state set para error, %d\n", sta);
143         return FM_PWR_MAX;
144     }
145 }
146
147 static volatile fm_s32 subsys_rst_state = FM_SUBSYS_RST_OFF;
148
149 fm_s32 fm_sys_state_get(struct fm *fmp)
150 {
151     return subsys_rst_state;
152 }
153
154 fm_s32 fm_sys_state_set(struct fm *fmp, fm_s32 sta)
155 {
156     if ((sta >= FM_SUBSYS_RST_OFF) && (sta < FM_SUBSYS_RST_MAX)) {
157         WCN_DBG(FM_NTC | MAIN, "sys state set from %d to %d\n", subsys_rst_state, sta);
158         subsys_rst_state = sta;
159     } else {
160         WCN_DBG(FM_ERR | MAIN, "sys state set para error, %d\n", sta);
161     }
162
163     return subsys_rst_state;
164 }
165
166
167 fm_s32 fm_subsys_reset(struct fm *fm)
168 {
169     //check if we are resetting
170     if (fm_sys_state_get(fm) != FM_SUBSYS_RST_OFF) {
171         WCN_DBG(FM_NTC | MAIN, "subsys reset is ongoing\n");
172         goto out;
173     }
174
175     FMR_ASSERT(fm);
176     fm->timer_wkthd->add_work(fm->timer_wkthd, fm->rst_wk);
177
178 out:
179     return 0;
180 }
181
182
183 fm_s32 fm_wholechip_rst_cb(fm_s32 sta)
184 {
185     struct fm *fm = g_fm_struct;
186     
187     if (!fm) return 0;
188
189     if (sta == 1) { 
190         if (fm_sys_state_get(fm) == FM_SUBSYS_RST_OFF) {
191             fm_sys_state_set(fm, FM_SUBSYS_RST_START);
192         }
193     } else {
194         fm->timer_wkthd->add_work(fm->timer_wkthd, fm->rst_wk);
195     }
196     return 0;
197 }
198
199
200 fm_s32 fm_open(struct fm *fmp)
201 {
202     fm_s32 ret = 0;
203 #if (defined(MT6620_FM)||defined(MT6628_FM))
204     fm_s32 chipid;
205 #endif
206     FMR_ASSERT(fmp);
207         if (current->pid == 1)
208                 return 0;
209     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
210
211     //makesure fmp->ref >= 0
212     fmp->ref = (fmp->ref < 0) ? 0 : fmp->ref;
213     fmp->ref++;
214
215     if ((fmp->ref > 0) && (fmp->chipon == fm_false)) 
216         {
217 #if (defined(MT6620_FM)||defined(MT6628_FM))
218                 chipid = mtk_wcn_wmt_chipid_query();
219                 WCN_DBG(FM_NTC | MAIN, "wmt chip id=0x%x\n",chipid);
220                 if(chipid == 0x6628)//get WCN chip ID
221                 {
222 #ifdef MT6628_FM
223                         fm_low_ops = MT6628fm_low_ops;
224                         fmp->chip_id = 0x6628;
225                         WCN_DBG(FM_NTC | MAIN, "get 6628 low ops\n");
226 #endif
227                 }
228                 else if(chipid == 0x6620)
229                 {
230 #ifdef MT6620_FM
231                         fm_low_ops = MT6620fm_low_ops;
232                         fmp->chip_id = 0x6620;
233                         WCN_DBG(FM_NTC | MAIN, "get 6620 low ops\n");
234 #endif
235                 }
236 #endif
237                 if(fm_low_ops.bi.pwron == NULL)
238                 {
239                         WCN_DBG(FM_NTC | MAIN, "get fm_low_ops fail\n");
240             fmp->ref--;
241             ret = -ENODEV;
242             goto out;
243         }
244
245         ret = fm_low_ops.bi.pwron(0);
246         if (ret) {
247             fmp->ref--;
248             ret = -ENODEV;
249             goto out;
250         }
251
252         fm_eint_pin_cfg(FM_EINT_PIN_EINT_MODE);
253         fm_request_eint(fm_eint_handler);
254         fmp->chipon = fm_true;
255     }
256
257 out:
258     WCN_DBG(FM_NTC | MAIN, "fm->ref:%d\n", fmp->ref);
259     FM_UNLOCK(fm_ops_lock);
260     return ret;
261 }
262
263 fm_s32 fm_close(struct fm *fmp)
264 {
265     fm_s32 ret = 0;
266
267     FMR_ASSERT(fmp);
268     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
269
270     fmp->ref--;
271
272     if (fmp->ref == 0) {
273         pwrdown_flow(fmp);
274         if (fmp->chipon == fm_true) {
275             fm_eint_pin_cfg(FM_EINT_PIN_GPIO_MODE);
276             fm_low_ops.bi.pwroff(0);
277             fmp->chipon = fm_false;
278         }
279     }
280
281     //makesure fm->ref >= 0
282     fmp->ref = (fmp->ref < 0) ? 0 : fmp->ref;
283     WCN_DBG(FM_NTC | MAIN, "fmp->ref:%d\n", fmp->ref);
284     FM_UNLOCK(fm_ops_lock);
285
286     return ret;
287 }
288 /*
289 fm_s32 fm_flush(struct fm *fmp)
290 {
291     fm_s32 ret = 0;
292
293     FMR_ASSERT(fmp);
294     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
295
296     if (FM_PWR_OFF == fm_pwr_state_get(fmp)) 
297     {
298         WCN_DBG(FM_NTC | MAIN, "should power off combo!\n");
299         if (fmp->chipon == fm_true) 
300         {
301             fm_low_ops.bi.pwroff(0);
302             fmp->chipon = fm_false;
303         }
304     }
305     WCN_DBG(FM_NTC | MAIN, "fm_flush done\n");
306     FM_UNLOCK(fm_ops_lock);
307
308     return ret;
309 }
310 */
311 fm_s32 fm_rds_read(struct fm *fmp, fm_s8 *dst, fm_s32 len)
312 {
313     fm_s32 copy_len = 0, left = 0;
314     copy_len = sizeof(rds_t);
315
316 RESTART:
317
318     if (FM_EVENT_GET(fmp->rds_event) == FM_RDS_DATA_READY) {
319         if (FM_LOCK(fm_read_lock)) return (-FM_ELOCK);
320
321         if ((left = copy_to_user((void *)dst, fmp->pstRDSData, (unsigned long)copy_len))) {
322             WCN_DBG(FM_ALT | MAIN, "fm_read copy failed\n");
323         } else {
324             fmp->pstRDSData->event_status = 0x0000;
325         }
326
327         WCN_DBG(FM_DBG | MAIN, "fm_read copy len:%d\n", (copy_len - left));
328
329         FM_EVENT_RESET(fmp->rds_event);
330         FM_UNLOCK(fm_read_lock);
331     } else {
332         if (FM_EVENT_WAIT(fmp->rds_event, FM_RDS_DATA_READY) == 0) {
333             WCN_DBG(FM_DBG | MAIN, "fm_read wait ok\n");
334             goto RESTART;
335         } else {
336             WCN_DBG(FM_ALT | MAIN, "fm_read wait err\n");
337             return 0;
338         }
339     }
340
341     return (copy_len - left);
342 }
343
344 fm_s32 fm_powerup(struct fm *fm, struct fm_tune_parm *parm)
345 {
346     fm_s32 ret = 0;
347
348     FMR_ASSERT(fm_low_ops.bi.pwron);
349     FMR_ASSERT(fm_low_ops.bi.pwrupseq);
350     FMR_ASSERT(fm_low_ops.bi.low_pwr_wa);
351     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
352
353     //for normal case
354     if (fm->chipon == fm_false) {
355         fm_low_ops.bi.pwron(0);
356         fm->chipon = fm_true;
357     }
358
359     if (FM_PWR_RX_ON == fm_pwr_state_get(fm)) {
360         WCN_DBG(FM_NTC | MAIN, "already pwron!\n");
361         goto out;
362     }
363         else if(FM_PWR_TX_ON == fm_pwr_state_get(fm))
364         {
365         //if Tx is on, we need pwr down TX first
366         ret = fm_powerdowntx(fm);
367         if(ret)
368                 {
369            WCN_DBG(FM_ERR | MAIN,"FM pwr down Tx fail!\n"); 
370            return ret;
371         }
372     }
373
374     fm_pwr_state_set(fm, FM_PWR_RX_ON);
375
376     //execute power on sequence
377     ret = fm_low_ops.bi.pwrupseq(&fm->chip_id, &fm->device_id);
378
379     if (ret) {
380         goto out;
381     }
382
383     fm_enable_eint();
384
385     WCN_DBG(FM_DBG | MAIN, "pwron ok\n");
386     fm_cur_freq_set(parm->freq);
387
388     parm->err = FM_SUCCESS;
389     fm_low_ops.bi.low_pwr_wa(1);
390
391     fm->vol = 15;
392         if(fm_low_ops.ri.rds_bci_get)
393         {
394                 fm_timer_sys->init(fm_timer_sys, fm_timer_func, (unsigned long)g_fm_struct, fm_low_ops.ri.rds_bci_get(), 0);
395                 fm_timer_sys->start(fm_timer_sys);
396                 WCN_DBG(FM_NTC | MAIN, "start timer ok\n");
397         }
398         else
399         {
400                 WCN_DBG(FM_NTC | MAIN, "start timer fail!!!\n");
401         }
402
403 out:
404     FM_UNLOCK(fm_ops_lock);
405     return ret;
406 }
407
408 /*
409  *  fm_powerup_tx
410  */
411 fm_s32 fm_powerup_tx(struct fm *fm, struct fm_tune_parm *parm)
412 {
413     fm_s32 ret = 0;
414
415     FMR_ASSERT(fm_low_ops.bi.pwron);
416     FMR_ASSERT(fm_low_ops.bi.pwrupseq_tx);
417
418     if (FM_PWR_TX_ON == fm_pwr_state_get(fm)) {
419         WCN_DBG(FM_NTC | MAIN, "already pwron!\n");
420         parm->err = FM_BADSTATUS;
421         goto out;
422     }
423         else if(FM_PWR_RX_ON == fm_pwr_state_get(fm))
424         {
425         //if Rx is on, we need pwr down  first
426         ret = fm_powerdown(fm);
427         if(ret)
428                 {
429            WCN_DBG(FM_ERR | MAIN,"FM pwr down Rx fail!\n"); 
430                    goto out;
431         }
432     }
433
434     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
435
436     //for normal case
437     if (fm->chipon == fm_false) {
438         fm_low_ops.bi.pwron(0);
439         fm->chipon = fm_true;
440     }
441     
442     fm_pwr_state_set(fm, FM_PWR_TX_ON);
443         ret = fm_low_ops.bi.pwrupseq_tx();
444
445         if(ret)
446         {
447                 parm->err = FM_FAILED; 
448         }
449         else
450         {
451                 parm->err = FM_SUCCESS; 
452         }
453     fm_cur_freq_set(parm->freq);
454         //if(fm_low_ops.ri.rds_bci_get)
455         {
456                 fm_timer_sys->count = 0;
457                 fm_timer_sys->tx_pwr_ctrl_en = FM_TX_PWR_CTRL_ENABLE;
458                 fm_timer_sys->tx_rtc_ctrl_en = FM_TX_RTC_CTRL_ENABLE;
459                 fm_timer_sys->tx_desense_en = FM_TX_DESENSE_ENABLE;
460         
461                 fm_timer_sys->init(fm_timer_sys, fmtx_timer_func, (unsigned long)g_fm_struct,FM_TIMER_TIMEOUT_MIN, 0);
462                 fm_timer_sys->start(fm_timer_sys);
463                 WCN_DBG(FM_NTC | MAIN, "start timer ok\n");
464         }
465
466 out:
467     FM_UNLOCK(fm_ops_lock);
468     return ret;
469 }
470
471 static fm_s32 pwrdown_flow(struct fm *fm)
472 {
473     fm_s32 ret = 0;
474     FMR_ASSERT(fm_low_ops.ri.rds_onoff);
475     FMR_ASSERT(fm_low_ops.bi.pwrdownseq);
476     FMR_ASSERT(fm_low_ops.bi.low_pwr_wa);
477     if (FM_PWR_OFF == fm_pwr_state_get(fm)) {
478         WCN_DBG(FM_NTC | MAIN, "already pwroff!\n");
479         goto out;
480     }
481         /*if(fm_low_ops.ri.rds_bci_get)
482         {
483                 fm_timer_sys->stop(fm_timer_sys);
484                 WCN_DBG(FM_NTC | MAIN, "stop timer ok\n");
485         }
486         else
487         {
488                 WCN_DBG(FM_NTC | MAIN, "stop timer fail!!!\n");
489         }*/
490     
491     //Disable all interrupt
492     fm_disable_rds_BlerCheck();
493     fm_low_ops.ri.rds_onoff(fm->pstRDSData, fm_false);
494     fm_disable_eint();
495
496     fm_pwr_state_set(fm, FM_PWR_OFF);
497
498     //execute power down sequence
499     ret = fm_low_ops.bi.pwrdownseq();
500
501     fm_low_ops.bi.low_pwr_wa(0);
502     WCN_DBG(FM_ALT | MAIN, "pwrdown_flow exit\n");
503
504 out:
505     return ret;
506 }
507
508 fm_s32 fm_powerdown(struct fm *fm)
509 {
510     fm_s32 ret = 0;
511         if (FM_PWR_TX_ON == fm_pwr_state_get(fm))
512         {
513             ret = fm_powerdowntx(fm);
514         }
515         else
516         {
517             if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
518             if (FM_LOCK(fm_rxtx_lock)) return(-FM_ELOCK);
519
520             ret = pwrdown_flow(fm);
521
522             FM_UNLOCK(fm_rxtx_lock);
523             FM_UNLOCK(fm_ops_lock);
524     }
525     return ret;
526 }
527
528 fm_s32 fm_powerdowntx(struct fm *fm)
529 {
530     fm_s32 ret = 0;
531
532     FMR_ASSERT(fm_low_ops.bi.pwrdownseq_tx);
533     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
534     if (FM_LOCK(fm_rxtx_lock)) return (-FM_ELOCK);
535
536     if (FM_PWR_TX_ON == fm_pwr_state_get(fm)) 
537     {
538                 if (FM_LOCK(fm_timer_lock)) return (-FM_ELOCK);
539                 fm_timer_sys->stop(fm_timer_sys);
540                 FM_UNLOCK(fm_timer_lock);
541                 fm_timer_sys->count = 0;
542                 fm_timer_sys->tx_pwr_ctrl_en = FM_TX_PWR_CTRL_DISABLE;
543                 fm_timer_sys->tx_rtc_ctrl_en = FM_TX_RTC_CTRL_DISABLE;
544                 fm_timer_sys->tx_desense_en = FM_TX_DESENSE_DISABLE;
545                 
546                 fm_low_ops.ri.rds_onoff(fm->pstRDSData, fm_false);
547                 //execute power down sequence
548                 ret = fm_low_ops.bi.pwrdownseq();
549                 if(ret)
550                 {
551                         WCN_DBG(FM_ERR | MAIN, "pwrdown tx 1 fail\n");
552                 }
553                 else
554                 {
555                         ret = fm_low_ops.bi.pwrdownseq_tx();
556                         if(ret)
557                         {
558                                 WCN_DBG(FM_ERR | MAIN, "pwrdown tx 2 fail\n");
559                         }
560                 }
561                 fm_pwr_state_set(fm, FM_PWR_OFF);
562                 WCN_DBG(FM_NTC | MAIN, "pwrdown tx ok\n");
563     }
564
565     FM_UNLOCK(fm_rxtx_lock);
566     FM_UNLOCK(fm_ops_lock);
567     return ret;
568 }
569
570 fm_s32 fm_seek(struct fm *fm, struct fm_seek_parm *parm)
571 {
572     fm_s32 ret = 0;
573     fm_u16 seekdir, space;
574
575     FMR_ASSERT(fm_low_ops.bi.seek);
576     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
577
578     if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) {
579         parm->err = FM_BADSTATUS;
580         ret = -EPERM;
581         goto out;
582     }
583
584     if (parm->space == FM_SPACE_100K) {
585         space = 0x0002;
586     } else if (parm->space == FM_SPACE_50K) {
587         space = 0x0001;
588     } else if (parm->space == FM_SPACE_200K) {
589         space = 0x0004;
590     } else {
591         //default
592         space = 0x0002;
593     }
594
595     if (parm->band == FM_BAND_UE) {
596         fm->min_freq = FM_UE_FREQ_MIN;
597         fm->max_freq = FM_UE_FREQ_MAX;
598     } else if (parm->band == FM_BAND_JAPANW) {
599         fm->min_freq = FM_JP_FREQ_MIN;
600         fm->max_freq = FM_JP_FREQ_MAX;
601     } else if (parm->band == FM_BAND_SPECIAL) {
602         fm->min_freq = FM_RX_BAND_FREQ_L;
603         fm->max_freq = FM_RX_BAND_FREQ_H;
604     } else {
605         WCN_DBG(FM_ALT | MAIN, "band:%d out of range\n", parm->band);
606         parm->err = FM_EPARM;
607         ret = -EPERM;
608         goto out;
609     }
610
611     if (parm->freq < fm->min_freq || parm->freq > fm->max_freq) {
612         WCN_DBG(FM_ALT | MAIN, "freq:%d out of range\n", parm->freq);
613         parm->err = FM_EPARM;
614         ret = -EPERM;
615         goto out;
616     }
617
618     if (parm->seekdir == FM_SEEK_UP) {
619         seekdir = FM_SEEK_UP;
620     } else {
621         seekdir = FM_SEEK_DOWN;
622     }
623
624     fm_op_state_set(fm, FM_STA_SEEK);
625
626     // seek successfully
627     if (fm_true == fm_low_ops.bi.seek(fm->min_freq, fm->max_freq, &(parm->freq), seekdir, space)) {
628         parm->err = FM_SUCCESS;
629     } else {
630         parm->err = FM_SEEK_FAILED;
631         ret = -EPERM;
632     }
633
634     if ((parm->space != FM_SPACE_50K) && (1 == fm_get_channel_space(parm->freq))) 
635     {
636         parm->freq /= 10; //(8750 / 10) = 875
637     }
638
639     fm_op_state_set(fm, FM_STA_PLAY);
640 out:
641     FM_UNLOCK(fm_ops_lock);
642     return ret;
643 }
644
645 /***********************************************************
646 Function:       fm_tx_scan()
647
648 Description:    get the valid channels for fm tx function
649
650 Para:           fm--->fm driver global info
651                         parm--->input/output paramater
652                         
653 Return:                 0, if success; error code, if failed
654 ***********************************************************/
655 fm_s32 fm_tx_scan(struct fm *fm, struct fm_tx_scan_parm *parm)
656 {
657     fm_s32 ret = 0;
658         fm_u16 scandir = 0;
659         fm_u16 space = FM_SPACE_100K;
660  
661         FMR_ASSERT(fm_low_ops.bi.tx_scan);
662
663         if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
664
665         if (fm->chipon != fm_true) 
666         {
667                 parm->err = FM_BADSTATUS;
668                 ret=-EPERM;
669                 WCN_DBG(FM_ERR | MAIN, "tx scan chip not on\n");
670                 goto out;
671         }
672         switch(parm->scandir){
673                 case FM_TX_SCAN_UP:
674                         scandir = 0;
675                         break;
676                 case FM_TX_SCAN_DOWN:
677                         scandir = 1;
678                         break;
679                 default:
680                         scandir = 0;
681                         break;
682         }
683         
684         /*if (parm->space == FM_SPACE_100K) {
685         space = 2;
686     } else if (parm->space == FM_SPACE_50K) {
687         space = 1;
688     } else if (parm->space == FM_SPACE_200K) {
689         space = 4;
690     } else {
691         //default
692         space = 2;
693         }*/
694         
695     if (parm->band == FM_BAND_UE) {
696         fm->min_freq = FM_UE_FREQ_MIN;
697         fm->max_freq = FM_UE_FREQ_MAX;
698     } else if (parm->band == FM_BAND_JAPANW) {
699         fm->min_freq = FM_JP_FREQ_MIN;
700         fm->max_freq = FM_JP_FREQ_MAX;
701     } else if (parm->band == FM_BAND_SPECIAL) {
702         fm->min_freq = FM_FREQ_MIN;
703         fm->max_freq = FM_FREQ_MAX;
704     } else 
705     {
706         WCN_DBG(FM_ERR| MAIN,"band:%d out of range\n", parm->band);
707                 parm->err = FM_EPARM;
708                 ret=-EPERM;
709                 goto out;
710         }
711
712     if (unlikely((parm->freq < fm->min_freq) || (parm->freq > fm->max_freq))){
713         parm->err = FM_EPARM;
714         ret=-EPERM;
715         goto out;
716     }
717
718         if (unlikely(parm->ScanTBLSize < TX_SCAN_MIN || parm->ScanTBLSize > TX_SCAN_MAX)){
719         parm->err = FM_EPARM;
720         ret=-EPERM;
721         goto out;
722     }
723
724     ret = fm_low_ops.bi.anaswitch(FM_ANA_SHORT);
725     if(ret){
726         WCN_DBG(FM_ERR | MAIN,"switch to short ana failed\n");
727         goto out;
728     }
729     
730         //do tx scan
731         if(!(ret = fm_low_ops.bi.tx_scan(fm->min_freq, fm->max_freq, &(parm->freq), 
732                                                                 parm->ScanTBL, &(parm->ScanTBLSize), scandir, space))){
733         parm->err = FM_SUCCESS;
734     }else{
735         WCN_DBG(FM_ERR | MAIN,"fm_tx_scan failed\n");
736         parm->err = FM_SCAN_FAILED;
737     }
738 out:    
739         FM_UNLOCK(fm_ops_lock);
740     return ret;
741 }
742
743 fm_s32  fm_scan(struct fm *fm, struct fm_scan_parm *parm)
744 {
745     fm_s32 ret = 0;
746     fm_u16 scandir = FM_SEEK_UP, space;
747
748     FMR_ASSERT(fm_low_ops.bi.scan);
749         WCN_DBG(FM_NTC | MAIN, "fm_scan:start\n");
750     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
751
752     if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) {
753         parm->err = FM_BADSTATUS;
754         ret = -EPERM;
755         goto out;
756     }
757
758     if (parm->space == FM_SPACE_100K) {
759         space = 0x0002;
760     } else if (parm->space == FM_SPACE_50K) {
761         space = 0x0001;
762     } else if (parm->space == FM_SPACE_200K) {
763         space = 0x0004;
764     } else {
765         //default
766         space = 0x0002;
767     }
768
769     if (parm->band == FM_BAND_UE) {
770         fm->min_freq = FM_UE_FREQ_MIN;
771         fm->max_freq = FM_UE_FREQ_MAX;
772     } else if (parm->band == FM_BAND_JAPANW) {
773         fm->min_freq = FM_JP_FREQ_MIN;
774         fm->max_freq = FM_JP_FREQ_MAX;
775     } else if (parm->band == FM_BAND_SPECIAL) {
776         fm->min_freq = FM_RX_BAND_FREQ_L;
777         fm->max_freq = FM_RX_BAND_FREQ_H;
778     } else {
779         WCN_DBG(FM_ALT | MAIN, "band:%d out of range\n", parm->band);
780         parm->err = FM_EPARM;
781         ret = -EPERM;
782         goto out;
783     }
784
785     fm_op_state_set(fm, FM_STA_SCAN);
786     scan_stop_flag = fm_false;
787
788     if (fm_true == fm_low_ops.bi.scan(fm->min_freq, fm->max_freq, &(parm->freq), parm->ScanTBL, &(parm->ScanTBLSize), scandir, space)) {
789         parm->err = FM_SUCCESS;
790     } else {
791         WCN_DBG(FM_ALT | MAIN, "fm_scan failed\n");
792         parm->err = FM_SEEK_FAILED;
793         ret = -EPERM;
794     }
795
796     fm_op_state_set(fm, FM_STA_STOP);
797
798 out:
799     FM_UNLOCK(fm_ops_lock);
800         WCN_DBG(FM_NTC | MAIN, "fm_scan:done\n");
801     return ret;
802 }
803
804
805 #define SCAN_SEG_LEN 250
806 static struct fm_cqi cqi_buf[SCAN_SEG_LEN];
807
808 fm_s32 fm_scan_new(struct fm *fm, struct fm_scan_t *parm)
809 {
810     fm_s32 ret = 0;
811     fm_s32 tmp;
812     fm_s32 cnt, seg;
813     fm_s32 i, j;
814     fm_s32 start_freq, end_freq;
815     fm_u16 scan_tbl[FM_SCANTBL_SIZE]; //need no less than the chip
816     fm_u16 tbl_size = FM_SCANTBL_SIZE;
817     fm_u16 tmp_freq = 0;
818     fm_s32 chl_cnt;
819     fm_s32 ch_offset, step, tmp_val;
820     fm_u16 space_idx = 0x0002;
821     
822     fm_s32 cqi_cnt, cqi_idx;
823     fm_s8 *buf = (fm_s8*)cqi_buf;
824     
825     FMR_ASSERT(fm_low_ops.bi.scan);
826     FMR_ASSERT(fm_low_ops.bi.cqi_get);
827     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
828
829     // caculate channel number, get segment count
830     cnt = (parm->upper - parm->lower) / parm->space + 1; //Eg, (10800 - 8750) / 5 = 411
831     seg = (cnt / SCAN_SEG_LEN) + ((cnt % SCAN_SEG_LEN) ? 1 : 0); //Eg, (411 / 200) + ((411 % 200) ? 1 : 0) = 2 + 1 = 3
832
833     WCN_DBG(FM_NTC | MAIN, "total ch %d, seg %d\n", cnt, seg);
834
835     // alloc memory
836     tmp = cnt * sizeof(struct fm_ch_rssi*);
837     if (parm->sr_size < tmp) {
838         if (parm->sr.ch_rssi_buf) {
839             fm_free(parm->sr.ch_rssi_buf);
840             parm->sr.ch_rssi_buf = NULL;
841         }
842         parm->sr_size = tmp;                
843     }
844     
845     if (!parm->sr.ch_rssi_buf) {
846         parm->sr.ch_rssi_buf = (struct fm_ch_rssi*)fm_zalloc(parm->sr_size);
847         if (!parm->sr.ch_rssi_buf) {
848             WCN_DBG(FM_ERR | MAIN, "scan alloc mem failed\n");
849             parm->sr_size = 0;
850             return -2;
851         }
852     }
853     
854     if (parm->space == 5) {
855         space_idx = 0x0001; // 50Khz
856     } else if (parm->space == 10) {
857         space_idx = 0x0002; // 100Khz
858     } else if (parm->space == 20) {
859         space_idx = 0x0004; // 200Khz
860     } 
861
862     
863     fm_op_state_set(fm, FM_STA_SCAN);
864     
865     // do scan
866     chl_cnt = 0;
867     for (i = 0; (i < seg) && (fm_false == scan_stop_flag); i++) {
868         cqi_cnt = 0;
869         cqi_idx = 0;
870         
871         start_freq = parm->lower + SCAN_SEG_LEN * parm->space * i;
872         end_freq = parm->lower + SCAN_SEG_LEN * parm->space * (i + 1) - parm->space;
873         end_freq = (end_freq > parm->upper) ? parm->upper : end_freq;
874
875         WCN_DBG(FM_NTC | MAIN, "seg %d, start %d, end %d\n", i, start_freq, end_freq);
876         if(fm_false == fm_low_ops.bi.scan(start_freq, end_freq, &tmp_freq, scan_tbl, &tbl_size, FM_SEEK_UP, space_idx)) {
877             ret = -1;
878             goto out;
879         }
880
881         // get channel count
882         for (ch_offset = 0; ch_offset < FM_SCANTBL_SIZE; ch_offset++) {
883                     if (scan_tbl[ch_offset] == 0)
884                             continue;
885                     for (step = 0; step < 16; step++) {
886                             if (scan_tbl[ch_offset] & (1 << step)) {
887                     tmp_val =  start_freq + (ch_offset * 16 + step) * parm->space;
888                     if (tmp_val <= end_freq) {
889                         // record valid  result channel
890                         WCN_DBG(FM_NTC | MAIN, "freq %d\n", tmp_val);
891                         parm->sr.ch_rssi_buf[chl_cnt].freq = tmp_val;
892                         chl_cnt++; 
893                         cqi_cnt++;
894                     }
895                             }
896                     }
897             }  
898
899         // get cqi
900         if(fm_low_ops.bi.cqi_get)
901         {
902                 tmp = cqi_cnt;
903                 while ((cqi_cnt > 0) && (fm_false == scan_stop_flag)) {
904                     ret = fm_low_ops.bi.cqi_get(buf + (16 * sizeof(struct fm_cqi) * cqi_idx), 
905                         sizeof(cqi_buf) - (16 * sizeof(struct fm_cqi) * cqi_idx));
906                     if (ret) {
907                         goto out;
908                     }
909
910                     cqi_cnt -= 16;
911                     cqi_idx++;
912                 }
913                 cqi_cnt = tmp;
914
915                 // fill cqi to result buffer
916                 for (j = 0; j < cqi_cnt; j++) {
917                     tmp = chl_cnt - cqi_cnt + j; // target pos
918                     parm->sr.ch_rssi_buf[tmp].freq = (fm_u16)cqi_buf[j].ch;
919                     parm->sr.ch_rssi_buf[tmp].rssi= cqi_buf[j].rssi;
920                     WCN_DBG(FM_NTC | MAIN, "idx %d, freq %d, rssi %d \n", tmp, parm->sr.ch_rssi_buf[tmp].freq, parm->sr.ch_rssi_buf[tmp].rssi);
921                 }
922         }
923         //6620 won't get rssi in scan new
924         //else if(fm_low_ops.bi.rssiget)
925     }
926      
927     fm_op_state_set(fm, FM_STA_STOP);
928     
929 out:
930     scan_stop_flag = fm_false;
931     FM_UNLOCK(fm_ops_lock);
932     parm->num = chl_cnt;
933     return ret;
934 }
935
936
937 fm_s32 fm_seek_new(struct fm *fm, struct fm_seek_t *parm)
938 {
939     fm_s32 ret = 0;
940     fm_s32 space_idx = 0x0002;
941
942     FMR_ASSERT(fm_low_ops.bi.setfreq);
943     FMR_ASSERT(fm_low_ops.bi.rssiget);
944     FMR_ASSERT(fm_low_ops.bi.rampdown);
945
946     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
947      
948     if (parm->freq < parm->lower || parm->freq > parm->upper) {
949         WCN_DBG(FM_ERR | MAIN, "seek start freq:%d out of range\n", parm->freq);
950         ret = -EPERM;
951         goto out;
952     }
953
954     // tune to start freq
955     fm_low_ops.bi.rampdown();
956     fm_low_ops.bi.setfreq(parm->freq);
957
958     if (parm->space == 5) {
959         space_idx = 0x0001;
960     } else if (parm->space == 10) {
961         space_idx = 0x0002;
962     } else if (parm->space == 20) {
963         space_idx = 0x0004;
964     }
965     
966     fm_op_state_set(fm, FM_STA_SEEK);
967     if (fm_false == fm_low_ops.bi.seek(parm->lower, parm->upper, &(parm->freq), parm->dir, space_idx)) {
968         ret = -1;
969         goto out;
970     } 
971
972     // tune to new channel
973     fm_low_ops.bi.setfreq(parm->freq);
974     fm_low_ops.bi.rssiget(&parm->th);
975     
976 out:
977     FM_UNLOCK(fm_ops_lock);
978     return ret;    
979 }
980
981
982 fm_s32 fm_tune_new(struct fm *fm, struct fm_tune_t *parm)
983 {
984     fm_s32 ret = 0;
985
986     FMR_ASSERT(fm_low_ops.bi.mute);
987     FMR_ASSERT(fm_low_ops.bi.rampdown);
988     FMR_ASSERT(fm_low_ops.bi.setfreq);
989
990     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
991
992     WCN_DBG(FM_DBG | MAIN, "%s\n", __func__);
993
994     if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) {
995         ret = -EPERM;
996         goto out;
997     }
998
999     if (parm->freq < parm->lower || parm->freq > parm->upper) {
1000         WCN_DBG(FM_ERR | MAIN, "tune freq:%d out of range\n", parm->freq);
1001         ret = -EPERM;
1002         goto out;
1003     }
1004     
1005 //    fm_low_ops.bi.mute(fm_true);
1006     fm_low_ops.bi.rampdown();
1007
1008     if (fm_cur_freq_get() != parm->freq) {
1009         fm_memset(fm->pstRDSData, 0, sizeof(rds_t));
1010     }
1011
1012 #if 0//(!defined(MT6620_FM)&&!defined(MT6628_FM))
1013     //HILO side adjust if need
1014     if (priv_adv.priv_tbl.hl_dese) {
1015         if ((ret = priv_adv.priv_tbl.hl_dese(parm->freq, NULL)) < 0) {
1016             goto out;
1017         }
1018
1019         WCN_DBG(FM_INF | MAIN, "HILO side %d\n", ret);
1020     }
1021
1022     //Frequency avoid adjust if need
1023     if (priv_adv.priv_tbl.fa_dese) {
1024         if ((ret = priv_adv.priv_tbl.fa_dese(parm->freq, NULL)) < 0) {
1025             goto out;
1026         }
1027
1028         WCN_DBG(FM_INF | MAIN, "FA %d\n", ret);
1029     }
1030
1031     //MCU clock adjust if need
1032     if (priv_adv.priv_tbl.mcu_dese) {
1033         if ((ret = priv_adv.priv_tbl.mcu_dese(parm->freq, NULL)) < 0) {
1034             goto out;
1035         }
1036
1037         WCN_DBG(FM_INF | MAIN, "MCU %d\n", ret);
1038     }
1039
1040     //GPS clock adjust if need
1041     if (priv_adv.priv_tbl.gps_dese) {
1042         if ((ret = priv_adv.priv_tbl.gps_dese(parm->freq, NULL)) < 0) {
1043             goto out;
1044         }
1045
1046         WCN_DBG(FM_INF | MAIN, "GPS %d\n", ret);
1047     }
1048 #endif
1049     fm_op_state_set(fm, FM_STA_TUNE);
1050     WCN_DBG(FM_ALT | MAIN, "tuning to %d\n", parm->freq);
1051
1052     if (fm_false == fm_low_ops.bi.setfreq(parm->freq)) {
1053         WCN_DBG(FM_ALT | MAIN, "FM tune failed\n");
1054         ret = -EPERM;
1055         goto out;
1056     }
1057
1058 //    fm_low_ops.bi.mute(fm_false);
1059     fm_op_state_set(fm, FM_STA_PLAY);
1060 out:
1061     FM_UNLOCK(fm_ops_lock);
1062     return ret;
1063 }
1064
1065
1066 fm_s32  fm_cqi_get(struct fm *fm, fm_s32 ch_num, fm_s8 *buf, fm_s32 buf_size)
1067 {
1068     fm_s32 ret = 0;
1069     fm_s32 idx = 0;
1070
1071     FMR_ASSERT(fm_low_ops.bi.cqi_get);
1072     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1073
1074     if (fm_true == scan_stop_flag) {
1075         WCN_DBG(FM_NTC | MAIN, "scan flow aborted, do not get CQI\n");
1076         ret = -1;
1077         goto out;
1078     }
1079     
1080     if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) {
1081         ret = -EPERM;
1082         goto out;
1083     }
1084
1085     if (ch_num*sizeof(struct fm_cqi) > buf_size) {
1086         ret = -EPERM;
1087         goto out;
1088     }
1089
1090     fm_op_state_set(fm, FM_STA_SCAN);
1091
1092     idx = 0;
1093     WCN_DBG(FM_NTC | MAIN, "cqi num %d\n", ch_num);
1094
1095     while (ch_num > 0) {
1096         ret = fm_low_ops.bi.cqi_get(buf + 16 * sizeof(struct fm_cqi) * idx, buf_size - 16 * sizeof(struct fm_cqi) * idx);
1097
1098         if (ret) {
1099             goto out;
1100         }
1101
1102         ch_num -= 16;
1103         idx++;
1104     }
1105
1106     fm_op_state_set(fm, FM_STA_STOP);
1107
1108 out:
1109     FM_UNLOCK(fm_ops_lock);
1110     return ret;
1111 }
1112
1113
1114 /*  fm_is_dese_chan -- check if gived channel is a de-sense channel or not
1115   *  @pfm - fm driver global DS
1116   *  @freq - gived channel
1117   *  return value: 0, not a dese chan; 1, a dese chan; else error NO.
1118   */
1119 fm_s32 fm_is_dese_chan(struct fm *pfm, fm_u16 freq)
1120 {
1121     fm_s32 ret = 0;
1122     FMR_ASSERT(pfm);
1123         if (fm_low_ops.bi.is_dese_chan) 
1124         {
1125         if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1126                 ret = fm_low_ops.bi.is_dese_chan(freq);
1127         FM_UNLOCK(fm_ops_lock);
1128         }
1129
1130         return ret;
1131 }
1132
1133
1134 /*  fm_is_dese_chan -- check if gived channel is a de-sense channel or not
1135   *  @pfm - fm driver global DS
1136   *  @freq - gived channel
1137   *  return value: 0, not a dese chan; 1, a dese chan; else error NO.
1138   */
1139 fm_s32 fm_desense_check(struct fm *pfm, fm_u16 freq,fm_s32 rssi)
1140 {
1141     fm_s32 ret = 0;
1142     FMR_ASSERT(pfm);
1143     if (fm_low_ops.bi.desense_check) 
1144         {
1145         if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1146         ret = fm_low_ops.bi.desense_check(freq,rssi);
1147         FM_UNLOCK(fm_ops_lock);
1148     }
1149
1150     return ret;
1151 }
1152 fm_s32 fm_dump_reg(void)
1153 {
1154     fm_s32 ret = 0;
1155     if (fm_low_ops.bi.dumpreg) 
1156     {
1157             if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1158         ret = fm_low_ops.bi.dumpreg();
1159             FM_UNLOCK(fm_ops_lock);
1160     }
1161     return ret;
1162 }
1163
1164 /*  fm_get_hw_info -- hw info: chip id, ECO version, DSP ROM version, Patch version
1165   *  @pfm - fm driver global DS
1166   *  @freq - target buffer
1167   *  return value: 0, success; else error NO.
1168   */
1169 fm_s32 fm_get_hw_info(struct fm *pfm, struct fm_hw_info *req)
1170 {
1171     fm_s32 ret = 0;
1172
1173     FMR_ASSERT(req);
1174
1175     //default value for all chips
1176     req->chip_id = 0x000066FF;
1177     req->eco_ver = 0x00000000;
1178     req->rom_ver = 0x00000001;
1179     req->patch_ver = 0x00000100;
1180     req->reserve = 0x00000000;
1181
1182     //get actual chip hw info
1183     if (fm_low_ops.bi.hwinfo_get) {
1184         if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1185         ret = fm_low_ops.bi.hwinfo_get(req);
1186         FM_UNLOCK(fm_ops_lock);
1187     }
1188
1189     return ret;
1190 }
1191
1192
1193 /*  fm_get_i2s_info -- i2s info: on/off, master/slave, sample rate
1194   *  @pfm - fm driver global DS
1195   *  @freq - target buffer
1196   *  return value: 0, success; else error NO.
1197   */
1198 fm_s32 fm_get_i2s_info(struct fm *pfm, struct fm_i2s_info *req)
1199 {
1200     FMR_ASSERT(req);
1201
1202     if (fm_low_ops.bi.i2s_get) {
1203         return fm_low_ops.bi.i2s_get(&req->status, &req->mode, &req->rate);
1204     } else {
1205         req->status = fm_i2s_inf.status;
1206         req->mode = fm_i2s_inf.mode;
1207         req->rate = fm_i2s_inf.rate;
1208
1209         return 0;
1210     }
1211 }
1212
1213
1214 fm_s32  fm_hwscan_stop(struct fm *fm)
1215 {
1216     fm_s32 ret = 0;
1217
1218     if ((FM_STA_SCAN != fm_op_state_get(fm))&&(FM_STA_SEEK!=fm_op_state_get(fm))) 
1219         {
1220         WCN_DBG(FM_WAR | MAIN, "fm isn't on scan, no need stop\n");
1221         return ret;
1222     }
1223
1224     FMR_ASSERT(fm_low_ops.bi.scanstop);
1225
1226     fm_low_ops.bi.scanstop();
1227     fm_low_ops.bi.seekstop();
1228     scan_stop_flag = fm_true;
1229     WCN_DBG(FM_DBG | MAIN, "fm will stop scan\n");
1230
1231     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1232     
1233     fm_low_ops.bi.rampdown();
1234     fm_low_ops.bi.setfreq(fm_cur_freq_get());
1235
1236     FM_UNLOCK(fm_ops_lock);
1237     
1238     return ret;
1239 }
1240
1241 /* fm_ana_switch -- switch antenna to long/short
1242  * @fm - fm driver main data structure
1243  * @antenna - 0, long; 1, short
1244  * If success, return 0; else error code
1245  */
1246 fm_s32 fm_ana_switch(struct fm *fm, fm_s32 antenna)
1247 {
1248     fm_s32 ret = 0;
1249
1250     FMR_ASSERT(fm_low_ops.bi.anaswitch);
1251     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1252
1253     WCN_DBG(FM_DBG | MAIN, "Switching ana to %s\n", antenna ? "short" : "long");
1254     fm->ana_type = antenna;
1255     ret = fm_low_ops.bi.anaswitch(antenna);
1256
1257     if (ret) {
1258         WCN_DBG(FM_ALT | MAIN, "Switch ana Failed\n");
1259     } else {
1260         WCN_DBG(FM_DBG | MAIN, "Switch ana OK!\n");
1261     }
1262
1263     FM_UNLOCK(fm_ops_lock);
1264     return ret;
1265 }
1266
1267 //volume?[0~15]
1268 fm_s32 fm_setvol(struct fm *fm, fm_u32 vol)
1269 {
1270     fm_u8 tmp_vol;
1271
1272     if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) {
1273                 return -EPERM;
1274     }
1275     FMR_ASSERT(fm_low_ops.bi.volset);
1276     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1277
1278     tmp_vol = (vol > 15) ? 15 : vol;
1279     fm_low_ops.bi.volset(tmp_vol);
1280     fm->vol = (fm_s32)tmp_vol;
1281
1282     FM_UNLOCK(fm_ops_lock);
1283     return 0;
1284 }
1285
1286 fm_s32 fm_getvol(struct fm *fm, fm_u32 *vol)
1287 {
1288     fm_u8 tmp_vol;
1289
1290     if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) {
1291                 return -EPERM;
1292     }
1293     FMR_ASSERT(fm_low_ops.bi.volget);
1294     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1295
1296     fm_low_ops.bi.volget(&tmp_vol);
1297     *vol = (fm_u32)tmp_vol;
1298
1299     FM_UNLOCK(fm_ops_lock);
1300     return 0;
1301 }
1302
1303 fm_s32 fm_mute(struct fm *fm, fm_u32 bmute)
1304 {
1305     fm_s32 ret = 0;
1306
1307     if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) {
1308         ret = -EPERM;
1309                 return ret;
1310     }
1311     FMR_ASSERT(fm_low_ops.bi.mute);
1312     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1313
1314     if (bmute) {
1315         ret = fm_low_ops.bi.mute(fm_true);
1316         fm->mute = fm_true;
1317     } else {
1318         ret = fm_low_ops.bi.mute(fm_false);
1319         fm->mute = fm_false;
1320     }
1321
1322     FM_UNLOCK(fm_ops_lock);
1323     return ret;
1324 }
1325
1326 fm_s32 fm_getrssi(struct fm *fm, fm_s32 *rssi)
1327 {
1328     fm_s32 ret = 0;
1329
1330     if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) {
1331         ret = -EPERM;
1332                 return ret;
1333     }
1334     FMR_ASSERT(fm_low_ops.bi.rssiget);
1335     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1336
1337     ret = fm_low_ops.bi.rssiget(rssi);
1338
1339     FM_UNLOCK(fm_ops_lock);
1340     return ret;
1341 }
1342
1343 fm_s32 fm_reg_read(struct fm *fm, fm_u8 addr, fm_u16 *val)
1344 {
1345     fm_s32 ret = 0;
1346
1347     FMR_ASSERT(fm_low_ops.bi.read);
1348     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1349
1350     ret = fm_low_ops.bi.read(addr, val);
1351
1352     FM_UNLOCK(fm_ops_lock);
1353     return ret;
1354 }
1355
1356 fm_s32 fm_reg_write(struct fm *fm, fm_u8 addr, fm_u16 val)
1357 {
1358     fm_s32 ret = 0;
1359
1360     FMR_ASSERT(fm_low_ops.bi.write);
1361     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1362
1363     ret = fm_low_ops.bi.write(addr, val);
1364
1365     FM_UNLOCK(fm_ops_lock);
1366     return ret;
1367 }
1368
1369 fm_s32 fm_chipid_get(struct fm *fm, fm_u16 *chipid)
1370 {
1371     FMR_ASSERT(chipid);
1372     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1373
1374     *chipid = fm->chip_id;
1375
1376     FM_UNLOCK(fm_ops_lock);
1377     return 0;
1378 }
1379
1380 fm_s32 fm_monostereo_get(struct fm *fm, fm_u16 *ms)
1381 {
1382     fm_s32 ret = 0;
1383
1384     FMR_ASSERT(fm_low_ops.bi.msget);
1385     FMR_ASSERT(ms);
1386     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1387
1388     if (fm_low_ops.bi.msget(ms) == fm_false) {
1389         ret = -FM_EPARA;
1390     }
1391
1392     FM_UNLOCK(fm_ops_lock);
1393     return ret;
1394 }
1395
1396 /*
1397  * Force set to stero/mono mode
1398  * @MonoStereo -- 0, auto; 1, mono
1399  * If success, return 0; else error code
1400  */
1401 fm_s32 fm_monostereo_set(struct fm *fm, fm_s32 ms)
1402 {
1403     fm_s32 ret = 0;
1404
1405     FMR_ASSERT(fm_low_ops.bi.msset);
1406     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1407
1408     ret = fm_low_ops.bi.msset(ms);
1409
1410     FM_UNLOCK(fm_ops_lock);
1411     return ret;
1412 }
1413
1414 fm_s32 fm_pamd_get(struct fm *fm, fm_u16 *pamd)
1415 {
1416     fm_s32 ret = 0;
1417
1418     FMR_ASSERT(fm_low_ops.bi.pamdget);
1419     FMR_ASSERT(pamd);
1420     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1421
1422     if (fm_low_ops.bi.pamdget(pamd) == fm_false) {
1423         ret = -FM_EPARA;
1424     }
1425
1426     FM_UNLOCK(fm_ops_lock);
1427     return ret;
1428 }
1429
1430 fm_s32 fm_caparray_get(struct fm *fm, fm_s32 *ca)
1431 {
1432     fm_s32 ret = 0;
1433
1434     FMR_ASSERT(fm_low_ops.bi.caparray_get);
1435     FMR_ASSERT(ca);
1436     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1437
1438     ret = fm_low_ops.bi.caparray_get(ca);
1439
1440     FM_UNLOCK(fm_ops_lock);
1441     return ret;
1442 }
1443
1444 fm_s32 fm_em_test(struct fm *fm, fm_u16 group, fm_u16 item, fm_u32 val)
1445 {
1446     fm_s32 ret = 0;
1447
1448     FMR_ASSERT(fm_low_ops.bi.em);
1449     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1450
1451     if (fm_false == fm_low_ops.bi.em(group, item, val)) {
1452         ret = -FM_EPARA;
1453     }
1454
1455     FM_UNLOCK(fm_ops_lock);
1456     return ret;
1457 }
1458
1459 fm_s32 fm_rds_tx(struct fm *fm, struct fm_rds_tx_parm *parm)
1460 {
1461     fm_s32 ret = 0;
1462
1463     FMR_ASSERT(fm_low_ops.ri.rds_tx);
1464     FMR_ASSERT(fm_low_ops.ri.rds_tx_enable);
1465
1466     if (fm_pwr_state_get(fm) != FM_PWR_TX_ON) {
1467         parm->err = FM_BADSTATUS;
1468         ret = -FM_EPARA;
1469         goto out;
1470     }
1471     if(parm->other_rds_cnt > 29)
1472     {
1473         parm->err = FM_EPARM;
1474         WCN_DBG(FM_ERR | MAIN,"other_rds_cnt=%d\n",parm->other_rds_cnt);
1475         ret = -FM_EPARA;
1476         goto out;
1477     }
1478     
1479     ret = fm_low_ops.ri.rds_tx_enable();
1480     if(ret){
1481         WCN_DBG(FM_ERR | MAIN,"Rds_Tx_Enable failed!\n");
1482         goto out;
1483     }   
1484     fm->rdstx_on = fm_true;
1485     ret = fm_low_ops.ri.rds_tx(parm->pi, parm->ps, parm->other_rds, parm->other_rds_cnt);
1486     if(ret){
1487         WCN_DBG(FM_ERR | MAIN,"Rds_Tx failed!\n");
1488         goto out;
1489     }   
1490 //    fm_cxt->txcxt.rdsTxOn = true;
1491 //    fm_cxt->txcxt.pi = parm->pi;
1492 //    memcpy(fm_cxt->txcxt.ps, parm->ps,sizeof(parm->ps));
1493 //    memcpy(fm_cxt->txcxt.other_rds, parm->other_rds,sizeof(parm->other_rds));
1494 //    fm_cxt->txcxt.other_rds_cnt = parm->other_rds_cnt; 
1495 out:
1496     return ret;
1497 }
1498
1499 fm_s32 fm_rds_onoff(struct fm *fm, fm_u16 rdson_off)
1500 {
1501     fm_s32 ret = 0;
1502
1503     FMR_ASSERT(fm_low_ops.ri.rds_onoff);
1504     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1505
1506     if (rdson_off) {
1507         fm->rds_on = fm_true;
1508         if (fm_low_ops.ri.rds_onoff(fm->pstRDSData, fm_true) == fm_false) {
1509             WCN_DBG(FM_ALT | MAIN, "FM_IOCTL_RDS_ONOFF faield\n");
1510             ret = -EPERM;
1511             goto out;
1512         }
1513
1514         fm_enable_rds_BlerCheck(fm);
1515     } else {
1516         fm->rds_on = fm_false;
1517         fm_disable_rds_BlerCheck();
1518         fm_low_ops.ri.rds_onoff(fm->pstRDSData, fm_false);
1519     }
1520
1521 out:
1522     FM_UNLOCK(fm_ops_lock);
1523     return ret;
1524 }
1525
1526 fm_s32 fm_rds_good_bc_get(struct fm *fm, fm_u16 *gbc)
1527 {
1528     fm_s32 ret = 0;
1529
1530     FMR_ASSERT(fm_low_ops.ri.rds_gbc_get);
1531     FMR_ASSERT(gbc);
1532     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1533
1534     *gbc = fm_low_ops.ri.rds_gbc_get();
1535
1536     FM_UNLOCK(fm_ops_lock);
1537     return ret;
1538 }
1539
1540 fm_s32 fm_rds_bad_bc_get(struct fm *fm, fm_u16 *bbc)
1541 {
1542     fm_s32 ret = 0;
1543
1544     FMR_ASSERT(fm_low_ops.ri.rds_bbc_get);
1545     FMR_ASSERT(bbc);
1546     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1547
1548     *bbc = fm_low_ops.ri.rds_bbc_get();
1549
1550     FM_UNLOCK(fm_ops_lock);
1551     return ret;
1552 }
1553
1554 fm_s32 fm_rds_bler_ratio_get(struct fm *fm, fm_u16 *bbr)
1555 {
1556     fm_s32 ret = 0;
1557
1558     FMR_ASSERT(fm_low_ops.ri.rds_bbr_get);
1559     FMR_ASSERT(bbr);
1560     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1561
1562     *bbr = (fm_u16)fm_low_ops.ri.rds_bbr_get();
1563
1564     FM_UNLOCK(fm_ops_lock);
1565     return ret;
1566 }
1567
1568 fm_s32 fm_rds_group_cnt_get(struct fm *fm, struct rds_group_cnt_t *dst)
1569 {
1570     fm_s32 ret = 0;
1571
1572     FMR_ASSERT(fm_low_ops.ri.rds_gc_get);
1573     FMR_ASSERT(dst);
1574     if (FM_LOCK(fm_rds_cnt)) return (-FM_ELOCK);
1575
1576     ret = fm_low_ops.ri.rds_gc_get(dst, fm->pstRDSData);
1577
1578     FM_UNLOCK(fm_rds_cnt);
1579     return ret;
1580 }
1581
1582 fm_s32 fm_rds_group_cnt_reset(struct fm *fm)
1583 {
1584     fm_s32 ret = 0;
1585
1586     FMR_ASSERT(fm_low_ops.ri.rds_gc_reset);
1587     if (FM_LOCK(fm_rds_cnt)) return (-FM_ELOCK);
1588
1589     ret = fm_low_ops.ri.rds_gc_reset(fm->pstRDSData);
1590
1591     FM_UNLOCK(fm_rds_cnt);
1592     return ret;
1593 }
1594
1595 fm_s32 fm_rds_log_get(struct fm *fm, struct rds_rx_t *dst, fm_s32 *dst_len)
1596 {
1597     fm_s32 ret = 0;
1598
1599     FMR_ASSERT(fm_low_ops.ri.rds_log_get);
1600     FMR_ASSERT(dst);
1601     FMR_ASSERT(dst_len);
1602     if (FM_LOCK(fm_read_lock)) return (-FM_ELOCK);
1603
1604     ret = fm_low_ops.ri.rds_log_get(dst, dst_len);
1605
1606     FM_UNLOCK(fm_read_lock);
1607     return ret;
1608 }
1609
1610 fm_s32 fm_rds_block_cnt_reset(struct fm *fm)
1611 {
1612     fm_s32 ret = 0;
1613
1614     FMR_ASSERT(fm_low_ops.ri.rds_bc_reset);
1615     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1616
1617     ret = fm_low_ops.ri.rds_bc_reset();
1618
1619     FM_UNLOCK(fm_ops_lock);
1620     return ret;
1621 }
1622
1623 fm_s32 fm_i2s_set(struct fm *fm, fm_s32 onoff, fm_s32 mode, fm_s32 sample)
1624 {
1625     fm_s32 ret = 0;
1626
1627     FMR_ASSERT(fm_low_ops.bi.i2s_set);
1628     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1629
1630     ret = fm_low_ops.bi.i2s_set(onoff, mode, sample);
1631
1632     FM_UNLOCK(fm_ops_lock);
1633     return ret;
1634 }
1635
1636 /*
1637  *  fm_tune_tx
1638  */
1639 fm_s32 fm_tune_tx(struct fm *fm, struct fm_tune_parm *parm)
1640 {
1641     fm_s32 ret = 0;
1642
1643     FMR_ASSERT(fm_low_ops.bi.tune_tx);
1644     
1645     if (fm_pwr_state_get(fm) != FM_PWR_TX_ON) {
1646         parm->err = FM_BADSTATUS;
1647         return -EPERM;
1648     }
1649     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1650     
1651     WCN_DBG(FM_DBG | MAIN, "%s\n", __func__);
1652
1653         fm_op_state_set(fm, FM_STA_TUNE);
1654         WCN_DBG(FM_NTC | MAIN, "Tx tune to %d\n", parm->freq);
1655 #if 0//ramp down tx will do in tx tune  flow
1656     while(0){
1657         if((ret = MT6620_RampDown_Tx()))
1658             return ret;
1659     }
1660 #endif
1661     //tune to desired channel
1662     if (fm_true != fm_low_ops.bi.tune_tx(parm->freq)) 
1663     {
1664         parm->err = FM_TUNE_FAILED;
1665         WCN_DBG(FM_ALT | MAIN, "Tx tune failed\n");
1666         ret = -EPERM;
1667     }
1668         fm_op_state_set(fm, FM_STA_PLAY);
1669         FM_UNLOCK(fm_ops_lock);
1670     
1671     return ret;
1672 }
1673
1674 /*
1675  *  fm_tune
1676  */
1677 fm_s32 fm_tune(struct fm *fm, struct fm_tune_parm *parm)
1678 {
1679     fm_s32 ret = 0;
1680
1681     FMR_ASSERT(fm_low_ops.bi.mute);
1682     FMR_ASSERT(fm_low_ops.bi.rampdown);
1683     FMR_ASSERT(fm_low_ops.bi.setfreq);
1684
1685     if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1686
1687     WCN_DBG(FM_DBG | MAIN, "%s\n", __func__);
1688
1689     if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) {
1690         parm->err = FM_BADSTATUS;
1691         ret = -EPERM;
1692         goto out;
1693     }
1694
1695 //    fm_low_ops.bi.mute(fm_true);
1696     fm_low_ops.bi.rampdown();
1697
1698     if (fm_cur_freq_get() != parm->freq) {
1699         fm_memset(fm->pstRDSData, 0, sizeof(rds_t));
1700     }
1701
1702 #if 0//(!defined(MT6620_FM)&&!defined(MT6628_FM))
1703     //HILO side adjust if need
1704     if (priv_adv.priv_tbl.hl_dese) {
1705         if ((ret = priv_adv.priv_tbl.hl_dese(parm->freq, NULL)) < 0) {
1706             goto out;
1707         }
1708
1709         WCN_DBG(FM_INF | MAIN, "HILO side %d\n", ret);
1710     }
1711
1712     //Frequency avoid adjust if need
1713     if (priv_adv.priv_tbl.fa_dese) {
1714         if ((ret = priv_adv.priv_tbl.fa_dese(parm->freq, NULL)) < 0) {
1715             goto out;
1716         }
1717
1718         WCN_DBG(FM_INF | MAIN, "FA %d\n", ret);
1719     }
1720
1721     //MCU clock adjust if need
1722     if (priv_adv.priv_tbl.mcu_dese) {
1723         if ((ret = priv_adv.priv_tbl.mcu_dese(parm->freq, NULL)) < 0) {
1724             goto out;
1725         }
1726
1727         WCN_DBG(FM_INF | MAIN, "MCU %d\n", ret);
1728     }
1729
1730     //GPS clock adjust if need
1731     if (priv_adv.priv_tbl.gps_dese) {
1732         if ((ret = priv_adv.priv_tbl.gps_dese(parm->freq, NULL)) < 0) {
1733             goto out;
1734         }
1735
1736         WCN_DBG(FM_INF | MAIN, "GPS %d\n", ret);
1737     }
1738 #endif
1739     fm_op_state_set(fm, FM_STA_TUNE);
1740     WCN_DBG(FM_ALT | MAIN, "tuning to %d\n", parm->freq);
1741
1742     if (fm_false == fm_low_ops.bi.setfreq(parm->freq)) {
1743         parm->err = FM_TUNE_FAILED;
1744         WCN_DBG(FM_ALT | MAIN, "FM tune failed\n");
1745         ret = -EPERM;
1746     }
1747
1748 //    fm_low_ops.bi.mute(fm_false);
1749     fm_op_state_set(fm, FM_STA_PLAY);
1750 out:
1751     FM_UNLOCK(fm_ops_lock);
1752     return ret;
1753 }
1754 //cqi log tool entry
1755 fm_s32 fm_cqi_log(void)
1756 {
1757     fm_s32 ret = 0;
1758     fm_u16 freq;
1759         FMR_ASSERT(fm_low_ops.bi.cqi_log);
1760     freq = fm_cur_freq_get();
1761     if (0 == fm_get_channel_space(freq)) {
1762         freq *= 10;
1763     }
1764     if((freq != 10000) && (0xffffffff != g_dbg_level))
1765     {
1766         return -FM_EPARA;
1767     }
1768         if (FM_LOCK(fm_ops_lock)) 
1769                 return (-FM_ELOCK);
1770         ret = fm_low_ops.bi.cqi_log(8750,10800,2,5);
1771     FM_UNLOCK(fm_ops_lock);
1772         return ret;
1773 }
1774 /*fm soft mute tune function*/
1775 fm_s32 fm_soft_mute_tune(struct fm *fm, struct fm_softmute_tune_t *parm)
1776 {
1777     fm_s32 ret = 0;
1778
1779         FMR_ASSERT(fm_low_ops.bi.softmute_tune);
1780         
1781         if (FM_LOCK(fm_ops_lock)) 
1782                 return (-FM_ELOCK);
1783         
1784         
1785         if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) 
1786         {
1787                 parm->valid = fm_false;
1788                 ret = -EPERM;
1789                 goto out;
1790         }
1791         
1792         //        fm_low_ops.bi.mute(fm_true);
1793         WCN_DBG(FM_NTC | MAIN, "+%s():[freq=%d]\n", __func__, parm->freq);
1794         //fm_op_state_set(fm, FM_STA_TUNE);
1795         
1796         if (fm_false == fm_low_ops.bi.softmute_tune(parm->freq,&parm->rssi,&parm->valid)) 
1797         {
1798                 parm->valid = fm_false;
1799                 WCN_DBG(FM_ALT | MAIN, "sm tune failed\n");
1800                 ret = -EPERM;
1801         }
1802         
1803 //        fm_low_ops.bi.mute(fm_false);
1804 out:
1805         WCN_DBG(FM_NTC | MAIN, "-%s()\n", __func__);
1806         FM_UNLOCK(fm_ops_lock);
1807                 
1808         return ret;
1809 }
1810 fm_s32 fm_over_bt(struct fm *fm, fm_s32 flag)
1811 {
1812     fm_s32 ret = 0;
1813         FMR_ASSERT(fm_low_ops.bi.fm_via_bt);
1814         
1815     if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) 
1816     {
1817         return -EPERM;
1818     }
1819         if (FM_LOCK(fm_ops_lock)) 
1820                 return (-FM_ELOCK);
1821    
1822     ret = fm_low_ops.bi.fm_via_bt(flag);
1823     if(ret)
1824     {
1825         WCN_DBG(FM_ALT | MAIN,"%s(),failed!\n", __func__);
1826     }
1827     else
1828     {
1829         fm->via_bt = flag;
1830     }
1831     WCN_DBG(FM_NTC | MAIN,"%s(),[ret=%d]!\n", __func__, ret);
1832         FM_UNLOCK(fm_ops_lock);
1833     return ret;
1834 }
1835 fm_s32 fm_tx_support(struct fm *fm, fm_s32 *support)
1836 {
1837         if (FM_LOCK(fm_ops_lock)) 
1838                 return (-FM_ELOCK);
1839         if(fm_low_ops.bi.tx_support)
1840         {
1841                 fm_low_ops.bi.tx_support(support);
1842         }
1843         else
1844         {
1845                 *support=0;
1846         }
1847     WCN_DBG(FM_NTC | MAIN,"%s(),[%d]!\n", __func__, *support);
1848         FM_UNLOCK(fm_ops_lock);
1849         return 0;
1850 }
1851 fm_s32 fm_rdstx_support(struct fm *fm, fm_s32 *support)
1852 {
1853         if (FM_LOCK(fm_ops_lock)) 
1854                 return (-FM_ELOCK);
1855         if(fm_low_ops.ri.rdstx_support)
1856         {
1857                 fm_low_ops.ri.rdstx_support(support);
1858         }
1859         else
1860         {
1861                 *support=0;
1862         }
1863     WCN_DBG(FM_NTC | MAIN,"support=[%d]!\n", *support);
1864         FM_UNLOCK(fm_ops_lock);
1865         return 0;
1866 }
1867 fm_s32 fm_rdstx_enable(struct fm *fm, fm_s32 *support)
1868 {
1869         if (FM_LOCK(fm_ops_lock)) 
1870                 return (-FM_ELOCK);
1871         if(fm->rdstx_on)
1872         {
1873                 *support=1;
1874         }
1875         else
1876         {
1877                 *support=0;
1878         }
1879     WCN_DBG(FM_NTC | MAIN,"rds tx enable=[%d]!\n", *support);
1880         FM_UNLOCK(fm_ops_lock);
1881         return 0;
1882 }
1883
1884 static void fm_timer_func(unsigned long data)
1885 {
1886     struct fm *fm = g_fm_struct;
1887
1888     if (FM_LOCK(fm_timer_lock)) return;
1889
1890     if (fm_timer_sys->update(fm_timer_sys)) {
1891                 WCN_DBG(FM_NTC | MAIN, "timer skip\n");
1892         goto out; //fm timer is stoped before timeout
1893     }
1894
1895     if (fm != NULL) {
1896                 WCN_DBG(FM_NTC | MAIN, "timer:rds_wk\n");
1897         fm->timer_wkthd->add_work(fm->timer_wkthd, fm->rds_wk);
1898     }
1899
1900 out:
1901     FM_UNLOCK(fm_timer_lock);
1902 }
1903
1904
1905 static void fmtx_timer_func(unsigned long data)
1906 {
1907     struct fm *fm = g_fm_struct;
1908     fm_s32 vco_cycle = 1;
1909
1910     if (FM_LOCK(fm_timer_lock)) return;
1911
1912     fm_timer_sys->count++; 
1913     if (fm != NULL) 
1914     {
1915                 //schedule tx pwr ctrl work if need
1916                 if(fm->txpwrctl < 1)
1917                 {
1918                         WCN_DBG(FM_WAR | MAIN,"tx power ctl time err\n");
1919                         fm->txpwrctl = FM_TX_PWR_CTRL_INVAL_MIN;
1920                 }
1921                 if((fm_timer_sys->tx_pwr_ctrl_en == FM_TX_PWR_CTRL_ENABLE) && (fm_timer_sys->count%fm->txpwrctl == 0))
1922                 {
1923                         WCN_DBG(FM_NTC | MAIN, "Tx timer:fm_tx_power_ctrl_work\n");
1924                         fm->timer_wkthd->add_work(fm->timer_wkthd, fm->fm_tx_power_ctrl_work); 
1925                 }
1926                 /*
1927                 //schedule tx RTC ctrl work if need
1928                 if((timer->tx_rtc_ctrl_en == FM_TX_RTC_CTRL_ENABLE)&& (timer->count%FM_TX_RTC_CTRL_INTERVAL == 0)){
1929                         FM_LOG_DBG(D_TIMER,"fm_tx_rtc_ctrl_work, ticks:%d\n", jiffies_to_msecs(jiffies));
1930                         queue_work(fm->fm_timer_workqueue, &fm->fm_tx_rtc_ctrl_work); 
1931                 }*/
1932                 //schedule tx desense with wifi/bt work if need
1933                 if(fm->vcooff < 1)
1934                 {
1935                         WCN_DBG(FM_WAR | MAIN,"tx vco tracking time err\n");
1936                         fm->vcooff = FM_TX_VCO_OFF_MIN;
1937                 }
1938                 vco_cycle = fm->vcooff + fm->vcoon/1000;
1939                 if((fm_timer_sys->tx_desense_en == FM_TX_DESENSE_ENABLE) && (fm_timer_sys->count%vco_cycle == 0))
1940                 {
1941                         WCN_DBG(FM_NTC | MAIN, "Tx timer:fm_tx_desense_wifi_work\n");
1942                         fm->timer_wkthd->add_work(fm->timer_wkthd, fm->fm_tx_desense_wifi_work); 
1943                 }
1944     }
1945     if (fm_timer_sys->update(fm_timer_sys)) {
1946                 WCN_DBG(FM_NTC | MAIN, "timer skip\n");
1947         goto out; //fm timer is stoped before timeout
1948     }
1949
1950 out:
1951     FM_UNLOCK(fm_timer_lock);
1952 }
1953
1954 static void fm_tx_power_ctrl_worker_func(unsigned long data)
1955 {
1956     fm_s32 ctrl = 0,ret=0;
1957     struct fm *fm = g_fm_struct;
1958
1959     WCN_DBG(FM_NTC | MAIN,"+%s():\n", __func__);
1960     
1961         if(fm_low_ops.bi.tx_pwr_ctrl == NULL)
1962                 return;
1963     if (FM_LOCK(fm_rxtx_lock)) return;
1964     
1965     if(fm_pwr_state_get(fm) != FM_PWR_TX_ON){
1966         WCN_DBG(FM_ERR | MAIN,"FM is not on TX mode\n");
1967         goto out;
1968     }
1969     
1970     ctrl = fm->tx_pwr;
1971     WCN_DBG(FM_NTC | MAIN,"tx pwr %ddb\n", ctrl);
1972     ret = fm_low_ops.bi.tx_pwr_ctrl(fm_cur_freq_get(), &ctrl);
1973     if(ret)
1974     {
1975         WCN_DBG(FM_ERR | MAIN,"tx_pwr_ctrl fail\n");
1976     }
1977     
1978 out:
1979     FM_UNLOCK(fm_rxtx_lock);
1980     WCN_DBG(FM_NTC | MAIN,"-%s()\n", __func__);
1981     return;
1982 }
1983 static void fm_tx_rtc_ctrl_worker_func(unsigned long data)
1984 {
1985     fm_s32 ret = 0;
1986     fm_s32 ctrl = 0;
1987     struct fm_gps_rtc_info rtcInfo;
1988     //struct timeval curTime;
1989     //struct fm *fm = (struct fm*)fm_cb;
1990     unsigned long curTime = 0;
1991
1992     WCN_DBG(FM_NTC | MAIN,"+%s():\n", __func__);
1993
1994     if(FM_LOCK(fm_rtc_mutex)) return;
1995     
1996     if(gps_rtc_info.flag == FM_GPS_RTC_INFO_NEW){
1997         memcpy(&rtcInfo, &gps_rtc_info, sizeof(struct fm_gps_rtc_info));
1998         gps_rtc_info.flag = FM_GPS_RTC_INFO_OLD;
1999         FM_UNLOCK(fm_rtc_mutex);
2000     }else{
2001         WCN_DBG(FM_NTC | MAIN,"there's no new rtc drift info\n");
2002         FM_UNLOCK(fm_rtc_mutex);
2003         goto out;
2004     }
2005
2006     if(rtcInfo.age > rtcInfo.ageThd){
2007        WCN_DBG(FM_WAR | MAIN,"age over it's threshlod\n");
2008        goto out;
2009     }
2010     if((rtcInfo.drift <= rtcInfo.driftThd) && (rtcInfo.drift >= -rtcInfo.driftThd)){
2011        WCN_DBG(FM_WAR | MAIN,"drift over it's MIN threshlod\n");
2012        goto out;
2013     }
2014
2015     if(rtcInfo.drift > FM_GPS_RTC_DRIFT_MAX){
2016         WCN_DBG(FM_WAR | MAIN,"drift over it's +MAX threshlod\n");
2017         rtcInfo.drift = FM_GPS_RTC_DRIFT_MAX;
2018         goto out;
2019     }else if(rtcInfo.drift < -FM_GPS_RTC_DRIFT_MAX){
2020         WCN_DBG(FM_WAR | MAIN,"drift over it's -MAX threshlod\n");
2021         rtcInfo.drift = -FM_GPS_RTC_DRIFT_MAX;
2022         goto out;
2023     }
2024     /*
2025     //get current time
2026     do_gettimeofday(&curTime);
2027     if((curTime.tv_sec - rtcInfo.tv.tv_sec) > rtcInfo.tvThd.tv_sec){
2028         FM_LOG_WAR(D_MAIN,"time diff over it's threshlod\n");
2029         goto out;
2030     }*/
2031     curTime = jiffies;
2032     if(((long)curTime - (long)rtcInfo.stamp)/HZ > rtcInfo.tvThd.tv_sec){
2033         WCN_DBG(FM_WAR | MAIN,"time diff over it's threshlod\n");
2034         goto out;
2035     }
2036     if(fm_low_ops.bi.rtc_drift_ctrl != NULL)
2037     {
2038         ctrl = rtcInfo.drift;
2039                 WCN_DBG(FM_NTC | MAIN,"RTC_drift_ctrl[0x%08x]\n", ctrl);
2040         if((ret = fm_low_ops.bi.rtc_drift_ctrl(fm_cur_freq_get(), &ctrl)))
2041             goto out;
2042     }
2043 out:
2044     WCN_DBG(FM_NTC | MAIN,"-%s()\n", __func__);
2045     return;
2046
2047
2048 static void fm_tx_desense_wifi_worker_func(unsigned long data)
2049 {
2050     fm_s32 ret = 0;
2051     fm_s32 ctrl = 0;
2052     struct fm *fm = g_fm_struct;
2053
2054     WCN_DBG(FM_NTC | MAIN,"+%s():\n", __func__);
2055
2056     if (FM_LOCK(fm_rxtx_lock)) return;
2057     
2058     if(fm_pwr_state_get(fm) != FM_PWR_TX_ON){
2059         WCN_DBG(FM_ERR | MAIN,"FM is not on TX mode\n");
2060         goto out;
2061     }
2062     
2063     fm_tx_rtc_ctrl_worker_func(0);
2064
2065     ctrl = fm->vcoon;
2066     if(fm_low_ops.bi.tx_desense_wifi)
2067     {
2068             WCN_DBG(FM_NTC | MAIN,"tx_desense_wifi[%d]\n", ctrl);
2069                 ret = fm_low_ops.bi.tx_desense_wifi(fm_cur_freq_get(), &ctrl);
2070             if(ret)
2071             {
2072                 WCN_DBG(FM_ERR | MAIN,"tx_desense_wifi fail\n");
2073             }
2074         }
2075 out:
2076     FM_UNLOCK(fm_rxtx_lock);
2077     WCN_DBG(FM_NTC | MAIN,"-%s()\n", __func__);
2078     return;
2079
2080
2081 /*
2082 ************************************************************************************
2083 Function:         fm_get_gps_rtc_info()
2084
2085 Description:     get GPS RTC drift info, and this function should not block
2086
2087 Date:              2011/04/10
2088
2089 Return Value:   success:0, failed: error coe
2090 ************************************************************************************
2091 */
2092 fm_s32 fm_get_gps_rtc_info(struct fm_gps_rtc_info *src)
2093 {
2094     fm_s32 ret = 0;
2095 //    fm_s32 retry_cnt = 0;
2096         struct fm_gps_rtc_info *dst=&gps_rtc_info; 
2097     
2098     FMR_ASSERT(src);
2099     FMR_ASSERT(dst);
2100
2101     if(src->retryCnt > 0){
2102         dst->retryCnt = src->retryCnt;
2103         WCN_DBG(FM_NTC | MAIN,"%s, new [retryCnt=%d]\n", __func__, dst->retryCnt);
2104     }
2105     if(src->ageThd > 0){
2106         dst->ageThd = src->ageThd;
2107         WCN_DBG(FM_NTC | MAIN,"%s, new [ageThd=%d]\n", __func__, dst->ageThd);
2108     }
2109     if(src->driftThd > 0){
2110         dst->driftThd = src->driftThd;
2111         WCN_DBG(FM_NTC | MAIN,"%s, new [driftThd=%d]\n", __func__, dst->driftThd);
2112     }
2113     if(src->tvThd.tv_sec > 0){
2114         dst->tvThd.tv_sec = src->tvThd.tv_sec;
2115         WCN_DBG(FM_NTC | MAIN,"%s, new [tvThd=%d]\n", __func__, (fm_s32)dst->tvThd.tv_sec);
2116     }
2117     ret = fm_rtc_mutex->trylock(fm_rtc_mutex,dst->retryCnt);
2118     if(ret)
2119     {
2120                 goto out;
2121     }
2122     dst->age = src->age;
2123     dst->drift = src->drift;
2124     dst->stamp = jiffies; //get curren time stamp
2125     dst->flag = FM_GPS_RTC_INFO_NEW;
2126     
2127     FM_UNLOCK(fm_rtc_mutex);
2128
2129    /*
2130     //send event to info fm_tx_rtc_ctrl_work
2131     if(timer_sys.tx_rtc_ctrl_en == FM_TX_RTC_CTRL_ENABLE){
2132         FM_LOG_DBG(D_TIMER,"fm_tx_rtc_ctrl_work, ticks:%d\n", jiffies_to_msecs(jiffies));
2133         queue_work(fm->fm_timer_workqueue, &fm->fm_tx_rtc_ctrl_work); 
2134     }
2135     */
2136     
2137 out:
2138     return ret;
2139 }
2140
2141 static void fm_enable_rds_BlerCheck(struct fm *fm)
2142 {
2143     if (FM_LOCK(fm_timer_lock)) return;
2144     fm_timer_sys->start(fm_timer_sys);
2145     FM_UNLOCK(fm_timer_lock);
2146 }
2147
2148 static void fm_disable_rds_BlerCheck(void)
2149 {
2150     if (FM_LOCK(fm_timer_lock)) return;
2151     fm_timer_sys->stop(fm_timer_sys);
2152     FM_UNLOCK(fm_timer_lock);
2153 }
2154
2155 void fm_rds_reset_work_func(unsigned long data)
2156 {
2157     fm_s32 ret = 0;
2158
2159     if (!fm_low_ops.ri.rds_blercheck) {
2160         return;
2161     }
2162     if (FM_LOCK(fm_rxtx_lock)) return;
2163
2164     if (FM_LOCK(fm_rds_cnt)) return;
2165     ret = fm_low_ops.ri.rds_blercheck(g_fm_struct->pstRDSData);
2166
2167         WCN_DBG(FM_NTC | MAIN, "Addr_Cnt=%x\n",g_fm_struct->pstRDSData->AF_Data.Addr_Cnt);
2168         if(g_fm_struct->pstRDSData->AF_Data.Addr_Cnt == 0xFF)//check af list get,can't use event==af_list because event will clear after read rds every time
2169         {
2170                 g_fm_struct->pstRDSData->event_status |= RDS_EVENT_AF;
2171         }
2172     if (!ret && g_fm_struct->pstRDSData->event_status) 
2173     {
2174         FM_EVENT_SEND(g_fm_struct->rds_event, FM_RDS_DATA_READY);
2175     }
2176         WCN_DBG(FM_NTC | MAIN, "rds event check=%x\n",g_fm_struct->pstRDSData->event_status);
2177     FM_UNLOCK(fm_rds_cnt);
2178     FM_UNLOCK(fm_rxtx_lock);
2179 }
2180
2181
2182 void fm_subsys_reset_work_func(unsigned long data)
2183 {
2184     g_dbg_level = 0xffffffff;
2185     if (FM_LOCK(fm_ops_lock)) return;
2186
2187     fm_sys_state_set(g_fm_struct, FM_SUBSYS_RST_START);
2188     
2189     if (g_fm_struct->chipon == fm_false)
2190         {
2191         WCN_DBG(FM_ALT | MAIN, "no need do recover\n");
2192         goto out;
2193     }
2194     // subsystem power off
2195     fm_low_ops.bi.pwroff(0);
2196     
2197     // prepare to reset
2198     
2199     // wait 3s
2200     fm_low_ops.bi.msdelay(2000);
2201     
2202     // subsystem power on
2203     fm_low_ops.bi.pwron(0);
2204     
2205     // recover context
2206     if (g_fm_struct->chipon == fm_false) {
2207         fm_low_ops.bi.pwroff(0);
2208         WCN_DBG(FM_ALT | MAIN, "no need do recover\n");
2209         goto out;
2210     }
2211
2212     if (FM_PWR_RX_ON == fm_pwr_state_get(g_fm_struct)) {
2213         fm_low_ops.bi.pwrupseq(&g_fm_struct->chip_id, &g_fm_struct->device_id);
2214     } else {
2215         WCN_DBG(FM_ALT | MAIN, "no need do re-powerup\n");
2216         goto out;
2217     }
2218
2219     fm_low_ops.bi.anaswitch(g_fm_struct->ana_type);
2220     
2221     fm_low_ops.bi.setfreq(fm_cur_freq_get()); 
2222
2223     fm_low_ops.bi.volset((fm_u8)g_fm_struct->vol);
2224
2225     fm_low_ops.bi.mute(g_fm_struct->mute);
2226
2227     fm_low_ops.ri.rds_onoff(g_fm_struct->pstRDSData, g_fm_struct->rds_on);
2228
2229     WCN_DBG(FM_ALT | MAIN, "recover done\n");
2230
2231 out:
2232     fm_sys_state_set(g_fm_struct, FM_SUBSYS_RST_END);
2233     fm_sys_state_set(g_fm_struct, FM_SUBSYS_RST_OFF);
2234
2235     FM_UNLOCK(fm_ops_lock);
2236     g_dbg_level = 0xfffffff5;
2237 }
2238
2239 static void fm_eint_handler(void)
2240 {
2241     struct fm *fm = g_fm_struct;
2242     WCN_DBG(FM_DBG | MAIN, "intr occur, ticks:%d\n", jiffies_to_msecs(jiffies));
2243
2244     if (fm != NULL) {
2245         fm->eint_wkthd->add_work(fm->eint_wkthd, fm->eint_wk);
2246     }
2247 }
2248
2249 static fm_s32 fm_rds_parser(struct rds_rx_t *rds_raw, fm_s32 rds_size)
2250 {
2251     struct fm *fm = g_fm_struct;//(struct fm *)work->data;
2252     rds_t *pstRDSData = fm->pstRDSData;
2253
2254     if (FM_LOCK(fm_read_lock)) return (-FM_ELOCK);
2255     //parsing RDS data
2256     fm_low_ops.ri.rds_parser(pstRDSData, rds_raw, rds_size, fm_cur_freq_get);
2257     FM_UNLOCK(fm_read_lock);
2258
2259     if ((pstRDSData->event_status != 0x0000) && (pstRDSData->event_status != RDS_EVENT_AF_LIST)) {
2260         WCN_DBG(FM_NTC | MAIN, "Notify user to read, [event:%04x]\n", pstRDSData->event_status);
2261         FM_EVENT_SEND(fm->rds_event, FM_RDS_DATA_READY);
2262     }
2263
2264     return 0;
2265 }
2266
2267 static void fm_eint_work_func(unsigned long data)
2268 {
2269     fm_event_parser(fm_rds_parser);
2270     //re-enable eint if need
2271     fm_enable_eint();
2272 }
2273
2274 static fm_s32 fm_callback_register(struct fm_lowlevel_ops *ops)
2275 {
2276     FMR_ASSERT(ops);
2277
2278     ops->cb.cur_freq_get = fm_cur_freq_get;
2279     ops->cb.cur_freq_set = fm_cur_freq_set;
2280     return 0;
2281 }
2282
2283 static fm_s32 fm_callback_unregister(struct fm_lowlevel_ops *ops)
2284 {
2285     FMR_ASSERT(ops);
2286
2287     fm_memset(&ops->cb, 0, sizeof(struct fm_callback));
2288     return 0;
2289 }
2290
2291
2292 static fm_s32 fm_para_init(struct fm *fmp)
2293 {
2294     FMR_ASSERT(fmp);
2295
2296     fmp->band = FM_BAND_SPECIAL;
2297     fmp->min_freq = FM_RX_BAND_FREQ_L;
2298     fmp->max_freq = FM_RX_BAND_FREQ_H;
2299     fmp->cur_freq = 0;
2300     
2301     return 0;
2302 }
2303
2304 fm_s32 fm_cust_config_setup(fm_s8 * filename)
2305 {
2306         fm_s32 ret;
2307 #if (defined(MT6620_FM)||defined(MT6628_FM))
2308 #ifdef MT6628_FM        
2309         ret = MT6628fm_cust_config_setup(filename);
2310         if(ret < 0)
2311         {
2312         WCN_DBG(FM_ERR | MAIN, "MT6628fm_cust_config_setup failed\n");
2313         }
2314 #endif
2315 #ifdef MT6620_FM
2316         ret = MT6620fm_cust_config_setup(filename);
2317         if(ret < 0)
2318         {
2319         WCN_DBG(FM_ERR | MAIN, "MT6620fm_cust_config_setup failed\n");
2320         }
2321 #endif
2322 #else
2323         fm_cust_config(filename);
2324         if(ret < 0)
2325         {
2326         WCN_DBG(FM_ERR | MAIN, "fm_cust_config failed\n");
2327         }
2328 #endif
2329         return ret;
2330 }
2331
2332 struct fm* fm_dev_init(fm_u32 arg) 
2333 {
2334     fm_s32 ret = 0;
2335     struct fm *fm = NULL;
2336
2337 //    if (!fm_low_ops.ri.rds_bci_get)
2338 //        return NULL;
2339
2340 //    if (!fm_low_ops.bi.chipid_get)
2341 //        return NULL;
2342
2343     //alloc fm main data structure
2344     if (!(fm = fm_zalloc(sizeof(struct fm)))) {
2345         WCN_DBG(FM_ALT | MAIN, "-ENOMEM\n");
2346         ret = -ENOMEM;
2347         goto ERR_EXIT;
2348     }
2349
2350     fm->ref = 0;
2351     fm->chipon = fm_false;
2352     fm_pwr_state_set(fm, FM_PWR_OFF);
2353 //    fm->chip_id = fm_low_ops.bi.chipid_get();
2354         //FM Tx
2355         fm->vcoon = FM_TX_VCO_ON_DEFAULT;
2356         fm->vcooff = FM_TX_VCO_OFF_DEFAULT;
2357         fm->txpwrctl = FM_TX_PWR_CTRL_INVAL_DEFAULT;
2358     fm->tx_pwr = FM_TX_PWR_LEVEL_MAX;
2359     gps_rtc_info.err = 0;
2360     gps_rtc_info.age = 0;
2361     gps_rtc_info.drift = 0;
2362     gps_rtc_info.tv.tv_sec = 0;
2363     gps_rtc_info.tv.tv_usec = 0;
2364     gps_rtc_info.ageThd = FM_GPS_RTC_AGE_TH;
2365     gps_rtc_info.driftThd = FM_GPS_RTC_DRIFT_TH;
2366     gps_rtc_info.tvThd.tv_sec = FM_GPS_RTC_TIME_DIFF_TH;
2367     gps_rtc_info.retryCnt = FM_GPS_RTC_RETRY_CNT;
2368     gps_rtc_info.flag = FM_GPS_RTC_INFO_OLD;
2369         
2370     if (!(fm->rds_event = fm_flag_event_create("fm_rds_event"))) {
2371         WCN_DBG(FM_ALT | MAIN, "-ENOMEM for RDS event\n");
2372         ret = -ENOMEM;
2373         goto ERR_EXIT;
2374     }
2375
2376     fm_flag_event_get(fm->rds_event);
2377
2378     //alloc fm rds data structure
2379     if (!(fm->pstRDSData = fm_zalloc(sizeof(rds_t)))) {
2380         WCN_DBG(FM_ALT | MAIN, "-ENOMEM for RDS\n");
2381         ret = -ENOMEM;
2382         goto ERR_EXIT;
2383     }
2384
2385     g_fm_struct = fm;
2386
2387     fm->timer_wkthd = fm_workthread_create("fm_timer_wq");
2388
2389     if (!fm->timer_wkthd) {
2390         WCN_DBG(FM_ALT | MAIN, "-ENOMEM for fm_timer_wq\n");
2391         ret = -ENOMEM;
2392         goto ERR_EXIT;
2393     }
2394
2395     fm_workthread_get(fm->timer_wkthd);
2396
2397     fm->eint_wkthd = fm_workthread_create("fm_eint_wq");
2398
2399     if (!fm->eint_wkthd) {
2400         WCN_DBG(FM_ALT | MAIN, "-ENOMEM for fm_eint_wq\n");
2401         ret = -ENOMEM;
2402         goto ERR_EXIT;
2403     }
2404
2405     fm_workthread_get(fm->eint_wkthd);
2406
2407     fm->eint_wk = fm_work_create("fm_eint_work");
2408
2409     if (!fm->eint_wk) {
2410         WCN_DBG(FM_ALT | MAIN, "-ENOMEM for eint_wk\n");
2411         ret = -ENOMEM;
2412         goto ERR_EXIT;
2413     } else {
2414         fm_work_get(fm->eint_wk);
2415         fm->eint_wk->init(fm->eint_wk, fm_eint_work_func, (unsigned long)fm);
2416     }
2417
2418     // create reset work
2419     fm->rst_wk = fm_work_create("fm_rst_work");
2420
2421     if (!fm->rst_wk) {
2422         WCN_DBG(FM_ALT | MAIN, "-ENOMEM for rst_wk\n");
2423         ret = -ENOMEM;
2424         goto ERR_EXIT;
2425     } else {
2426         fm_work_get(fm->rst_wk);
2427         fm->rst_wk->init(fm->rst_wk, fm_subsys_reset_work_func, (unsigned long)fm);
2428     }
2429
2430     fm->rds_wk = fm_work_create("fm_rds_work");
2431     if (!fm->rds_wk) {
2432         WCN_DBG(FM_ALT | MAIN, "-ENOMEM for rds_wk\n");
2433         ret = -ENOMEM;
2434         goto ERR_EXIT;
2435     } else {
2436         fm_work_get(fm->rds_wk);
2437         fm->rds_wk->init(fm->rds_wk, fm_rds_reset_work_func, (unsigned long)fm);
2438     }
2439     
2440     fm->fm_tx_power_ctrl_work = fm_work_create("tx_pwr_ctl_work");
2441     if (!fm->fm_tx_power_ctrl_work) {
2442         WCN_DBG(FM_ALT | MAIN, "-ENOMEM for tx_pwr_ctl_work\n");
2443         ret = -ENOMEM;
2444         goto ERR_EXIT;
2445     } else {
2446         fm_work_get(fm->fm_tx_power_ctrl_work);
2447         fm->fm_tx_power_ctrl_work->init(fm->fm_tx_power_ctrl_work, fm_tx_power_ctrl_worker_func, (unsigned long)fm);
2448     }
2449     
2450     fm->fm_tx_desense_wifi_work = fm_work_create("tx_desen_wifi_work");
2451     if (!fm->fm_tx_desense_wifi_work) {
2452         WCN_DBG(FM_ALT | MAIN, "-ENOMEM for tx_desen_wifi_work\n");
2453         ret = -ENOMEM;
2454         goto ERR_EXIT;
2455     } else {
2456         fm_work_get(fm->fm_tx_desense_wifi_work);
2457         fm->fm_tx_desense_wifi_work->init(fm->fm_tx_desense_wifi_work, fm_tx_desense_wifi_worker_func, (unsigned long)fm);
2458     }
2459
2460     //fm timer was created in fm_env_setp()
2461 //    fm_timer_sys->init(fm_timer_sys, fm_timer_func, (unsigned long)g_fm_struct, fm_low_ops.ri.rds_bci_get(), 0);
2462 //    fm_timer_sys->start(fm_timer_sys);
2463
2464     //init customer config parameter
2465     fm_cust_config_setup(NULL);
2466
2467     fm_para_init(fm);
2468     
2469     return g_fm_struct;
2470
2471 ERR_EXIT:
2472
2473     if (fm->eint_wkthd) {
2474         ret = fm_workthread_put(fm->eint_wkthd);
2475
2476         if (!ret)
2477             fm->eint_wkthd = NULL;
2478     }
2479
2480     if (fm->timer_wkthd) {
2481         ret = fm_workthread_put(fm->timer_wkthd);
2482
2483         if (!ret)
2484             fm->timer_wkthd = NULL;
2485     }
2486
2487     if (fm->eint_wk) {
2488         ret = fm_work_put(fm->eint_wk);
2489
2490         if (!ret)
2491             fm->eint_wk = NULL;
2492     }
2493
2494     if (fm->rds_wk) {
2495         ret = fm_work_put(fm->rds_wk);
2496
2497         if (!ret)
2498             fm->rds_wk = NULL;
2499     }
2500
2501     if (fm->rst_wk) {
2502         ret = fm_work_put(fm->rst_wk);
2503
2504         if (!ret)
2505             fm->rst_wk = NULL;
2506     }
2507     
2508     if (fm->fm_tx_desense_wifi_work) {
2509         ret = fm_work_put(fm->fm_tx_desense_wifi_work);
2510
2511         if (!ret)
2512             fm->fm_tx_desense_wifi_work = NULL;
2513     }
2514     
2515     if (fm->fm_tx_power_ctrl_work) {
2516         ret = fm_work_put(fm->fm_tx_power_ctrl_work);
2517
2518         if (!ret)
2519             fm->fm_tx_power_ctrl_work = NULL;
2520     }
2521     
2522     if (fm->pstRDSData) {
2523         fm_free(fm->pstRDSData);
2524         fm->pstRDSData = NULL;
2525     }
2526
2527     fm_free(fm);
2528     g_fm_struct = NULL;
2529     return NULL;
2530 }
2531
2532 fm_s32 fm_dev_destroy(struct fm *fm)
2533 {
2534     fm_s32 ret = 0;
2535
2536     WCN_DBG(FM_DBG | MAIN, "%s\n", __func__);
2537
2538     fm_timer_sys->stop(fm_timer_sys);
2539
2540     if (fm->eint_wkthd) {
2541         ret = fm_workthread_put(fm->eint_wkthd);
2542
2543         if (!ret)
2544             fm->eint_wkthd = NULL;
2545     }
2546
2547     if (fm->timer_wkthd) {
2548         ret = fm_workthread_put(fm->timer_wkthd);
2549
2550         if (!ret)
2551             fm->timer_wkthd = NULL;
2552     }
2553
2554     if (fm->eint_wk) {
2555         ret = fm_work_put(fm->eint_wk);
2556
2557         if (!ret)
2558             fm->eint_wk = NULL;
2559     }
2560
2561     if (fm->rds_wk) {
2562         ret = fm_work_put(fm->rds_wk);
2563
2564         if (!ret)
2565             fm->rds_wk = NULL;
2566     }
2567
2568     if (fm->rst_wk) {
2569         ret = fm_work_put(fm->rst_wk);
2570
2571         if (!ret)
2572             fm->rst_wk = NULL;
2573     }
2574     
2575     if (fm->pstRDSData) {
2576         fm_free(fm->pstRDSData);
2577         fm->pstRDSData = NULL;
2578     }
2579
2580     if (fm->pstRDSData) {
2581         fm_free(fm->pstRDSData);
2582         fm->pstRDSData = NULL;
2583     }
2584
2585     fm_flag_event_put(fm->rds_event);
2586
2587     // free all memory
2588     if (fm) {
2589         fm_free(fm);
2590         fm = NULL;
2591         g_fm_struct = NULL;
2592     }
2593
2594     return ret;
2595 }
2596
2597 fm_s32 fm_env_setup(void)
2598 {
2599     fm_s32 ret = 0;
2600
2601     WCN_DBG(FM_NTC | MAIN, "%s\n", __func__);
2602 #if (defined(MT6620_FM)||defined(MT6628_FM))
2603 #ifdef MT6620_FM        
2604     //register call back functions
2605     ret = fm_callback_register(&MT6620fm_low_ops);
2606     if (ret) {
2607         return ret;
2608     }
2609     WCN_DBG(FM_NTC | MAIN, "1. fm callback registered\n");
2610     //get low level functions
2611     ret = MT6620fm_low_ops_register(&MT6620fm_low_ops);
2612     if (ret) {
2613         return ret;
2614     }
2615     WCN_DBG(FM_NTC | MAIN, "2. fm low ops registered\n");
2616     //get rds level functions
2617     ret = MT6620fm_rds_ops_register(&MT6620fm_low_ops);
2618     if (ret) {
2619         return ret;
2620     }
2621     WCN_DBG(FM_NTC | MAIN, "3. fm rds ops registered\n");
2622 #endif  
2623 #ifdef MT6628_FM        
2624     //register call back functions
2625     ret = fm_callback_register(&MT6628fm_low_ops);
2626     if (ret) {
2627         return ret;
2628     }
2629     WCN_DBG(FM_NTC | MAIN, "1. fm callback registered\n");
2630     //get low level functions
2631     ret = MT6628fm_low_ops_register(&MT6628fm_low_ops);
2632     if (ret) {
2633         return ret;
2634     }
2635     WCN_DBG(FM_NTC | MAIN, "2. fm low ops registered\n");
2636     //get rds level functions
2637     ret = MT6628fm_rds_ops_register(&MT6628fm_low_ops);
2638     if (ret) {
2639         return ret;
2640     }
2641     WCN_DBG(FM_NTC | MAIN, "3. fm rds ops registered\n");
2642 #endif  
2643 #else 
2644     //register call back functions
2645     ret = fm_callback_register(&fm_low_ops);
2646     if (ret) {
2647         return ret;
2648     }
2649     WCN_DBG(FM_NTC | MAIN, "1. fm callback registered\n");
2650     //get low level functions
2651     ret = fm_low_ops_register(&fm_low_ops);
2652
2653     if (ret) {
2654         return ret;
2655     }
2656
2657     WCN_DBG(FM_NTC | MAIN, "2. fm low ops registered\n");
2658     //get rds level functions
2659     ret = fm_rds_ops_register(&fm_low_ops);
2660
2661     if (ret) {
2662         return ret;
2663     }
2664     WCN_DBG(FM_NTC | MAIN, "3. fm rds ops registered\n");
2665 #endif
2666
2667     fm_ops_lock = fm_lock_create("ops_lock");
2668
2669     if (!fm_ops_lock) {
2670         return -1;
2671     }
2672
2673     fm_read_lock = fm_lock_create("rds_read");
2674
2675     if (!fm_read_lock) {
2676         return -1;
2677     }
2678     
2679     fm_rds_cnt = fm_lock_create("rds_cnt");
2680
2681     if (!fm_rds_cnt) {
2682         return -1;
2683     }
2684
2685     fm_timer_lock = fm_spin_lock_create("timer_lock");
2686
2687     if (!fm_timer_lock) {
2688         return -1;
2689     }
2690         fm_rxtx_lock = fm_lock_create("rxtx_lock");
2691     if (!fm_rxtx_lock) {
2692         return -1;
2693     }
2694         fm_rtc_mutex = fm_lock_create("rxtx_lock");
2695     if (!fm_rxtx_lock) {
2696         return -1;
2697     }
2698
2699     fm_lock_get(fm_ops_lock);
2700     fm_lock_get(fm_read_lock);
2701     fm_lock_get(fm_rds_cnt);
2702     fm_spin_lock_get(fm_timer_lock);
2703     fm_lock_get(fm_rxtx_lock);
2704     WCN_DBG(FM_NTC | MAIN, "4. fm locks created\n");
2705
2706     fm_timer_sys = fm_timer_create("fm_sys_timer");
2707
2708     if (!fm_timer_sys) {
2709         return -1;
2710     }
2711
2712     fm_timer_get(fm_timer_sys);
2713     WCN_DBG(FM_NTC | MAIN, "5. fm timer created\n");
2714
2715     ret = fm_link_setup((void*)fm_wholechip_rst_cb);
2716
2717     if (ret) {
2718         WCN_DBG(FM_ERR | MAIN, "fm link setup Failed\n");
2719         return -1;
2720     }
2721
2722     return ret;
2723 }
2724
2725 fm_s32 fm_env_destroy(void)
2726 {
2727     fm_s32 ret = 0;
2728
2729     WCN_DBG(FM_NTC | MAIN, "%s\n", __func__);
2730
2731     fm_link_release();
2732
2733 #if (defined(MT6620_FM)||defined(MT6628_FM))
2734 #if defined(MT6620_FM)
2735     //register call back functions
2736                 ret = fm_callback_unregister(&MT6620fm_low_ops);
2737
2738     if (ret) {
2739         return -1;
2740     }
2741                 //put low level functions
2742                 ret = MT6620fm_low_ops_unregister(&MT6620fm_low_ops);
2743         
2744                 if (ret) {
2745                         return -1;
2746                 }
2747         
2748                 //put rds func
2749                 ret = MT6620fm_rds_ops_unregister(&MT6620fm_low_ops);
2750         
2751                 if (ret) {
2752                         return -1;
2753                 }
2754 #endif
2755 #if defined(MT6628_FM)
2756                 //register call back functions
2757                 ret = fm_callback_unregister(&MT6628fm_low_ops);
2758
2759                 if (ret) {
2760                         return -1;
2761                 }
2762                 //put low level functions
2763                 ret = MT6628fm_low_ops_unregister(&MT6628fm_low_ops);
2764
2765                 if (ret) {
2766                         return -1;
2767                 }
2768         
2769                 //put rds func
2770                 ret = MT6628fm_rds_ops_unregister(&MT6628fm_low_ops);
2771         
2772                 if (ret) {
2773                         return -1;
2774                 }
2775 #endif
2776 #else
2777     //register call back functions
2778     ret = fm_callback_unregister(&fm_low_ops);
2779
2780     if (ret) {
2781         return -1;
2782     }
2783     //put low level functions
2784     ret = fm_low_ops_unregister(&fm_low_ops);
2785
2786     if (ret) {
2787         return -1;
2788     }
2789
2790     //put rds func
2791     ret = fm_rds_ops_unregister(&fm_low_ops);
2792
2793     if (ret) {
2794         return -1;
2795     }
2796 #endif
2797     ret = fm_lock_put(fm_ops_lock);
2798
2799     if (!ret)
2800         fm_ops_lock = NULL;
2801
2802     ret = fm_lock_put(fm_read_lock);
2803
2804     if (!ret)
2805         fm_read_lock = NULL;
2806
2807     ret = fm_lock_put(fm_rds_cnt);
2808
2809     if (!ret)
2810         fm_rds_cnt = NULL;
2811     ret = fm_spin_lock_put(fm_timer_lock);
2812
2813     if (!ret)
2814         fm_timer_lock = NULL;
2815
2816     ret = fm_timer_put(fm_timer_sys);
2817
2818     if (!ret)
2819         fm_timer_sys = NULL;
2820
2821     return ret;
2822 }
2823
2824 #if 0//(!defined(MT6620_FM)&&!defined(MT6628_FM))
2825 fm_s32 fm_priv_register(struct fm_priv *pri, struct fm_pub *pub)
2826 {
2827     fm_s32 ret = 0;
2828     //Basic functions.
2829
2830     WCN_DBG(FM_NTC | MAIN, "%s\n", __func__);
2831     FMR_ASSERT(pri);
2832     FMR_ASSERT(pub);
2833
2834     // functions provided by private module
2835     priv_adv.priv_tbl.hl_dese = pri->priv_tbl.hl_dese;
2836     priv_adv.priv_tbl.fa_dese = pri->priv_tbl.fa_dese;
2837     priv_adv.priv_tbl.mcu_dese = pri->priv_tbl.mcu_dese;
2838     priv_adv.priv_tbl.gps_dese = pri->priv_tbl.gps_dese;
2839     priv_adv.priv_tbl.chan_para_get = pri->priv_tbl.chan_para_get;
2840     priv_adv.priv_tbl.is_dese_chan = pri->priv_tbl.is_dese_chan;
2841     priv_adv.state = INITED;
2842     priv_adv.data = NULL;
2843
2844     // for special chip(chip with DSP) use
2845     fm_low_ops.cb.chan_para_get = priv_adv.priv_tbl.chan_para_get;
2846
2847     // private module will use these functions
2848     pub->pub_tbl.read = fm_low_ops.bi.read;
2849     pub->pub_tbl.write = fm_low_ops.bi.write;
2850     pub->pub_tbl.setbits = fm_low_ops.bi.setbits;
2851     pub->pub_tbl.rampdown = fm_low_ops.bi.rampdown;
2852     pub->pub_tbl.msdelay = fm_low_ops.bi.msdelay;
2853     pub->pub_tbl.usdelay = fm_low_ops.bi.usdelay;
2854     pub->pub_tbl.log = (fm_s32 (*)(const fm_s8 *arg1, ...))printk;
2855     pub->state = INITED;
2856     pub->data = NULL;
2857
2858     return ret;
2859 }
2860
2861 fm_s32 fm_priv_unregister(struct fm_priv *pri, struct fm_pub *pub)
2862 {
2863     WCN_DBG(FM_NTC | MAIN, "%s\n", __func__);
2864
2865     //FMR_ASSERT(pri);
2866     FMR_ASSERT(pub);
2867
2868     fm_memset(&priv_adv, 0, sizeof(struct fm_priv));
2869     fm_low_ops.cb.chan_para_get = NULL;
2870     fm_memset(pub, 0, sizeof(struct fm_pub));
2871
2872     return 0;
2873 }
2874 #endif
2875
2876 /*
2877  * GetChannelSpace - get the spcace of gived channel
2878  * @freq - value in 760~1080 or 7600~10800
2879  *
2880  * Return 0, if 760~1080; return 1, if 7600 ~ 10800, else err code < 0
2881  */
2882 fm_s32 fm_get_channel_space(fm_s32 freq)
2883 {
2884     if ((freq >= 760) && (freq <= 1080)) {
2885         return 0;
2886     } else if ((freq >= 7600) && (freq <= 10800)) {
2887         return 1;
2888     } else {
2889         return -1;
2890     }
2891 }
2892