4 * MediaTek <www.MediaTek.com>
5 * Hongcheng <hongcheng.xia@MediaTek.com>
7 * FM Radio Driver -- main functions
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.
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.
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
23 #include <linux/kernel.h>
24 #include <asm/uaccess.h>
25 #include <linux/slab.h>
28 #include "fm_config.h"
29 //#include "fm_cust_cfg.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;
36 static struct fm_lowlevel_ops MT6620fm_low_ops;
39 static struct fm_lowlevel_ops MT6628fm_low_ops;
41 //MTK FM Radio private advanced features
42 #if 0//(!defined(MT6620_FM)&&!defined(MT6628_FM))
43 static struct fm_priv priv_adv;
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
56 static struct fm_timer *fm_timer_sys;
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
64 static fm_bool scan_stop_flag = fm_false;
65 static struct fm_gps_rtc_info gps_rtc_info;
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);
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);
86 static fm_s32 pwrdown_flow(struct fm *fm);
88 static fm_u16 fm_cur_freq_get(void)
90 return g_fm_struct ? g_fm_struct->cur_freq : 0;
93 static fm_s32 fm_cur_freq_set(fm_u16 new_freq)
96 g_fm_struct->cur_freq = new_freq;
101 static enum fm_op_state fm_op_state_get(struct fm *fmp)
104 WCN_DBG(FM_DBG | MAIN, "op state get %d\n", fmp->op_sta);
107 WCN_DBG(FM_ERR | MAIN, "op state get para error\n");
108 return FM_STA_UNKOWN;
112 static enum fm_op_state fm_op_state_set(struct fm *fmp, enum fm_op_state sta)
114 if (fmp && (sta < FM_STA_MAX)) {
116 WCN_DBG(FM_DBG | MAIN, "op state set to %d\n", sta);
119 WCN_DBG(FM_ERR | MAIN, "op state set para error, %d\n", sta);
120 return FM_STA_UNKOWN;
124 enum fm_pwr_state fm_pwr_state_get(struct fm *fmp)
127 WCN_DBG(FM_DBG | MAIN, "pwr state get %d\n", fmp->pwr_sta);
130 WCN_DBG(FM_ERR | MAIN, "pwr state get para error\n");
135 enum fm_pwr_state fm_pwr_state_set(struct fm *fmp, enum fm_pwr_state sta)
137 if (fmp && (sta < FM_PWR_MAX)) {
139 WCN_DBG(FM_NTC | MAIN, "pwr state set to %d\n", sta);
142 WCN_DBG(FM_ERR | MAIN, "pwr state set para error, %d\n", sta);
147 static volatile fm_s32 subsys_rst_state = FM_SUBSYS_RST_OFF;
149 fm_s32 fm_sys_state_get(struct fm *fmp)
151 return subsys_rst_state;
154 fm_s32 fm_sys_state_set(struct fm *fmp, fm_s32 sta)
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;
160 WCN_DBG(FM_ERR | MAIN, "sys state set para error, %d\n", sta);
163 return subsys_rst_state;
167 fm_s32 fm_subsys_reset(struct fm *fm)
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");
176 fm->timer_wkthd->add_work(fm->timer_wkthd, fm->rst_wk);
183 fm_s32 fm_wholechip_rst_cb(fm_s32 sta)
185 struct fm *fm = g_fm_struct;
190 if (fm_sys_state_get(fm) == FM_SUBSYS_RST_OFF) {
191 fm_sys_state_set(fm, FM_SUBSYS_RST_START);
194 fm->timer_wkthd->add_work(fm->timer_wkthd, fm->rst_wk);
200 fm_s32 fm_open(struct fm *fmp)
203 #if (defined(MT6620_FM)||defined(MT6628_FM))
207 if (current->pid == 1)
209 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
211 //makesure fmp->ref >= 0
212 fmp->ref = (fmp->ref < 0) ? 0 : fmp->ref;
215 if ((fmp->ref > 0) && (fmp->chipon == fm_false))
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
223 fm_low_ops = MT6628fm_low_ops;
224 fmp->chip_id = 0x6628;
225 WCN_DBG(FM_NTC | MAIN, "get 6628 low ops\n");
228 else if(chipid == 0x6620)
231 fm_low_ops = MT6620fm_low_ops;
232 fmp->chip_id = 0x6620;
233 WCN_DBG(FM_NTC | MAIN, "get 6620 low ops\n");
237 if(fm_low_ops.bi.pwron == NULL)
239 WCN_DBG(FM_NTC | MAIN, "get fm_low_ops fail\n");
245 ret = fm_low_ops.bi.pwron(0);
252 fm_eint_pin_cfg(FM_EINT_PIN_EINT_MODE);
253 fm_request_eint(fm_eint_handler);
254 fmp->chipon = fm_true;
258 WCN_DBG(FM_NTC | MAIN, "fm->ref:%d\n", fmp->ref);
259 FM_UNLOCK(fm_ops_lock);
263 fm_s32 fm_close(struct fm *fmp)
268 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
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;
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);
289 fm_s32 fm_flush(struct fm *fmp)
294 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
296 if (FM_PWR_OFF == fm_pwr_state_get(fmp))
298 WCN_DBG(FM_NTC | MAIN, "should power off combo!\n");
299 if (fmp->chipon == fm_true)
301 fm_low_ops.bi.pwroff(0);
302 fmp->chipon = fm_false;
305 WCN_DBG(FM_NTC | MAIN, "fm_flush done\n");
306 FM_UNLOCK(fm_ops_lock);
311 fm_s32 fm_rds_read(struct fm *fmp, fm_s8 *dst, fm_s32 len)
313 fm_s32 copy_len = 0, left = 0;
314 copy_len = sizeof(rds_t);
318 if (FM_EVENT_GET(fmp->rds_event) == FM_RDS_DATA_READY) {
319 if (FM_LOCK(fm_read_lock)) return (-FM_ELOCK);
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");
324 fmp->pstRDSData->event_status = 0x0000;
327 WCN_DBG(FM_DBG | MAIN, "fm_read copy len:%d\n", (copy_len - left));
329 FM_EVENT_RESET(fmp->rds_event);
330 FM_UNLOCK(fm_read_lock);
332 if (FM_EVENT_WAIT(fmp->rds_event, FM_RDS_DATA_READY) == 0) {
333 WCN_DBG(FM_DBG | MAIN, "fm_read wait ok\n");
336 WCN_DBG(FM_ALT | MAIN, "fm_read wait err\n");
341 return (copy_len - left);
344 fm_s32 fm_powerup(struct fm *fm, struct fm_tune_parm *parm)
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);
354 if (fm->chipon == fm_false) {
355 fm_low_ops.bi.pwron(0);
356 fm->chipon = fm_true;
359 if (FM_PWR_RX_ON == fm_pwr_state_get(fm)) {
360 WCN_DBG(FM_NTC | MAIN, "already pwron!\n");
363 else if(FM_PWR_TX_ON == fm_pwr_state_get(fm))
365 //if Tx is on, we need pwr down TX first
366 ret = fm_powerdowntx(fm);
369 WCN_DBG(FM_ERR | MAIN,"FM pwr down Tx fail!\n");
374 fm_pwr_state_set(fm, FM_PWR_RX_ON);
376 //execute power on sequence
377 ret = fm_low_ops.bi.pwrupseq(&fm->chip_id, &fm->device_id);
385 WCN_DBG(FM_DBG | MAIN, "pwron ok\n");
386 fm_cur_freq_set(parm->freq);
388 parm->err = FM_SUCCESS;
389 fm_low_ops.bi.low_pwr_wa(1);
392 if(fm_low_ops.ri.rds_bci_get)
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");
400 WCN_DBG(FM_NTC | MAIN, "start timer fail!!!\n");
404 FM_UNLOCK(fm_ops_lock);
411 fm_s32 fm_powerup_tx(struct fm *fm, struct fm_tune_parm *parm)
415 FMR_ASSERT(fm_low_ops.bi.pwron);
416 FMR_ASSERT(fm_low_ops.bi.pwrupseq_tx);
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;
423 else if(FM_PWR_RX_ON == fm_pwr_state_get(fm))
425 //if Rx is on, we need pwr down first
426 ret = fm_powerdown(fm);
429 WCN_DBG(FM_ERR | MAIN,"FM pwr down Rx fail!\n");
434 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
437 if (fm->chipon == fm_false) {
438 fm_low_ops.bi.pwron(0);
439 fm->chipon = fm_true;
442 fm_pwr_state_set(fm, FM_PWR_TX_ON);
443 ret = fm_low_ops.bi.pwrupseq_tx();
447 parm->err = FM_FAILED;
451 parm->err = FM_SUCCESS;
453 fm_cur_freq_set(parm->freq);
454 //if(fm_low_ops.ri.rds_bci_get)
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;
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");
467 FM_UNLOCK(fm_ops_lock);
471 static fm_s32 pwrdown_flow(struct fm *fm)
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");
481 /*if(fm_low_ops.ri.rds_bci_get)
483 fm_timer_sys->stop(fm_timer_sys);
484 WCN_DBG(FM_NTC | MAIN, "stop timer ok\n");
488 WCN_DBG(FM_NTC | MAIN, "stop timer fail!!!\n");
491 //Disable all interrupt
492 fm_disable_rds_BlerCheck();
493 fm_low_ops.ri.rds_onoff(fm->pstRDSData, fm_false);
496 fm_pwr_state_set(fm, FM_PWR_OFF);
498 //execute power down sequence
499 ret = fm_low_ops.bi.pwrdownseq();
501 fm_low_ops.bi.low_pwr_wa(0);
502 WCN_DBG(FM_ALT | MAIN, "pwrdown_flow exit\n");
508 fm_s32 fm_powerdown(struct fm *fm)
511 if (FM_PWR_TX_ON == fm_pwr_state_get(fm))
513 ret = fm_powerdowntx(fm);
517 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
518 if (FM_LOCK(fm_rxtx_lock)) return(-FM_ELOCK);
520 ret = pwrdown_flow(fm);
522 FM_UNLOCK(fm_rxtx_lock);
523 FM_UNLOCK(fm_ops_lock);
528 fm_s32 fm_powerdowntx(struct fm *fm)
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);
536 if (FM_PWR_TX_ON == fm_pwr_state_get(fm))
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;
546 fm_low_ops.ri.rds_onoff(fm->pstRDSData, fm_false);
547 //execute power down sequence
548 ret = fm_low_ops.bi.pwrdownseq();
551 WCN_DBG(FM_ERR | MAIN, "pwrdown tx 1 fail\n");
555 ret = fm_low_ops.bi.pwrdownseq_tx();
558 WCN_DBG(FM_ERR | MAIN, "pwrdown tx 2 fail\n");
561 fm_pwr_state_set(fm, FM_PWR_OFF);
562 WCN_DBG(FM_NTC | MAIN, "pwrdown tx ok\n");
565 FM_UNLOCK(fm_rxtx_lock);
566 FM_UNLOCK(fm_ops_lock);
570 fm_s32 fm_seek(struct fm *fm, struct fm_seek_parm *parm)
573 fm_u16 seekdir, space;
575 FMR_ASSERT(fm_low_ops.bi.seek);
576 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
578 if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) {
579 parm->err = FM_BADSTATUS;
584 if (parm->space == FM_SPACE_100K) {
586 } else if (parm->space == FM_SPACE_50K) {
588 } else if (parm->space == FM_SPACE_200K) {
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;
605 WCN_DBG(FM_ALT | MAIN, "band:%d out of range\n", parm->band);
606 parm->err = FM_EPARM;
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;
618 if (parm->seekdir == FM_SEEK_UP) {
619 seekdir = FM_SEEK_UP;
621 seekdir = FM_SEEK_DOWN;
624 fm_op_state_set(fm, FM_STA_SEEK);
627 if (fm_true == fm_low_ops.bi.seek(fm->min_freq, fm->max_freq, &(parm->freq), seekdir, space)) {
628 parm->err = FM_SUCCESS;
630 parm->err = FM_SEEK_FAILED;
634 if ((parm->space != FM_SPACE_50K) && (1 == fm_get_channel_space(parm->freq)))
636 parm->freq /= 10; //(8750 / 10) = 875
639 fm_op_state_set(fm, FM_STA_PLAY);
641 FM_UNLOCK(fm_ops_lock);
645 /***********************************************************
646 Function: fm_tx_scan()
648 Description: get the valid channels for fm tx function
650 Para: fm--->fm driver global info
651 parm--->input/output paramater
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)
659 fm_u16 space = FM_SPACE_100K;
661 FMR_ASSERT(fm_low_ops.bi.tx_scan);
663 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
665 if (fm->chipon != fm_true)
667 parm->err = FM_BADSTATUS;
669 WCN_DBG(FM_ERR | MAIN, "tx scan chip not on\n");
672 switch(parm->scandir){
676 case FM_TX_SCAN_DOWN:
684 /*if (parm->space == FM_SPACE_100K) {
686 } else if (parm->space == FM_SPACE_50K) {
688 } else if (parm->space == FM_SPACE_200K) {
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;
706 WCN_DBG(FM_ERR| MAIN,"band:%d out of range\n", parm->band);
707 parm->err = FM_EPARM;
712 if (unlikely((parm->freq < fm->min_freq) || (parm->freq > fm->max_freq))){
713 parm->err = FM_EPARM;
718 if (unlikely(parm->ScanTBLSize < TX_SCAN_MIN || parm->ScanTBLSize > TX_SCAN_MAX)){
719 parm->err = FM_EPARM;
724 ret = fm_low_ops.bi.anaswitch(FM_ANA_SHORT);
726 WCN_DBG(FM_ERR | MAIN,"switch to short ana failed\n");
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;
735 WCN_DBG(FM_ERR | MAIN,"fm_tx_scan failed\n");
736 parm->err = FM_SCAN_FAILED;
739 FM_UNLOCK(fm_ops_lock);
743 fm_s32 fm_scan(struct fm *fm, struct fm_scan_parm *parm)
746 fm_u16 scandir = FM_SEEK_UP, space;
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);
752 if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) {
753 parm->err = FM_BADSTATUS;
758 if (parm->space == FM_SPACE_100K) {
760 } else if (parm->space == FM_SPACE_50K) {
762 } else if (parm->space == FM_SPACE_200K) {
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;
779 WCN_DBG(FM_ALT | MAIN, "band:%d out of range\n", parm->band);
780 parm->err = FM_EPARM;
785 fm_op_state_set(fm, FM_STA_SCAN);
786 scan_stop_flag = fm_false;
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;
791 WCN_DBG(FM_ALT | MAIN, "fm_scan failed\n");
792 parm->err = FM_SEEK_FAILED;
796 fm_op_state_set(fm, FM_STA_STOP);
799 FM_UNLOCK(fm_ops_lock);
800 WCN_DBG(FM_NTC | MAIN, "fm_scan:done\n");
805 #define SCAN_SEG_LEN 250
806 static struct fm_cqi cqi_buf[SCAN_SEG_LEN];
808 fm_s32 fm_scan_new(struct fm *fm, struct fm_scan_t *parm)
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;
819 fm_s32 ch_offset, step, tmp_val;
820 fm_u16 space_idx = 0x0002;
822 fm_s32 cqi_cnt, cqi_idx;
823 fm_s8 *buf = (fm_s8*)cqi_buf;
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);
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
833 WCN_DBG(FM_NTC | MAIN, "total ch %d, seg %d\n", cnt, seg);
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;
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");
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
863 fm_op_state_set(fm, FM_STA_SCAN);
867 for (i = 0; (i < seg) && (fm_false == scan_stop_flag); i++) {
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;
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)) {
882 for (ch_offset = 0; ch_offset < FM_SCANTBL_SIZE; ch_offset++) {
883 if (scan_tbl[ch_offset] == 0)
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;
900 if(fm_low_ops.bi.cqi_get)
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));
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);
923 //6620 won't get rssi in scan new
924 //else if(fm_low_ops.bi.rssiget)
927 fm_op_state_set(fm, FM_STA_STOP);
930 scan_stop_flag = fm_false;
931 FM_UNLOCK(fm_ops_lock);
937 fm_s32 fm_seek_new(struct fm *fm, struct fm_seek_t *parm)
940 fm_s32 space_idx = 0x0002;
942 FMR_ASSERT(fm_low_ops.bi.setfreq);
943 FMR_ASSERT(fm_low_ops.bi.rssiget);
944 FMR_ASSERT(fm_low_ops.bi.rampdown);
946 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
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);
954 // tune to start freq
955 fm_low_ops.bi.rampdown();
956 fm_low_ops.bi.setfreq(parm->freq);
958 if (parm->space == 5) {
960 } else if (parm->space == 10) {
962 } else if (parm->space == 20) {
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)) {
972 // tune to new channel
973 fm_low_ops.bi.setfreq(parm->freq);
974 fm_low_ops.bi.rssiget(&parm->th);
977 FM_UNLOCK(fm_ops_lock);
982 fm_s32 fm_tune_new(struct fm *fm, struct fm_tune_t *parm)
986 FMR_ASSERT(fm_low_ops.bi.mute);
987 FMR_ASSERT(fm_low_ops.bi.rampdown);
988 FMR_ASSERT(fm_low_ops.bi.setfreq);
990 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
992 WCN_DBG(FM_DBG | MAIN, "%s\n", __func__);
994 if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) {
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);
1005 // fm_low_ops.bi.mute(fm_true);
1006 fm_low_ops.bi.rampdown();
1008 if (fm_cur_freq_get() != parm->freq) {
1009 fm_memset(fm->pstRDSData, 0, sizeof(rds_t));
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) {
1019 WCN_DBG(FM_INF | MAIN, "HILO side %d\n", ret);
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) {
1028 WCN_DBG(FM_INF | MAIN, "FA %d\n", ret);
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) {
1037 WCN_DBG(FM_INF | MAIN, "MCU %d\n", ret);
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) {
1046 WCN_DBG(FM_INF | MAIN, "GPS %d\n", ret);
1049 fm_op_state_set(fm, FM_STA_TUNE);
1050 WCN_DBG(FM_ALT | MAIN, "tuning to %d\n", parm->freq);
1052 if (fm_false == fm_low_ops.bi.setfreq(parm->freq)) {
1053 WCN_DBG(FM_ALT | MAIN, "FM tune failed\n");
1058 // fm_low_ops.bi.mute(fm_false);
1059 fm_op_state_set(fm, FM_STA_PLAY);
1061 FM_UNLOCK(fm_ops_lock);
1066 fm_s32 fm_cqi_get(struct fm *fm, fm_s32 ch_num, fm_s8 *buf, fm_s32 buf_size)
1071 FMR_ASSERT(fm_low_ops.bi.cqi_get);
1072 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1074 if (fm_true == scan_stop_flag) {
1075 WCN_DBG(FM_NTC | MAIN, "scan flow aborted, do not get CQI\n");
1080 if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) {
1085 if (ch_num*sizeof(struct fm_cqi) > buf_size) {
1090 fm_op_state_set(fm, FM_STA_SCAN);
1093 WCN_DBG(FM_NTC | MAIN, "cqi num %d\n", ch_num);
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);
1106 fm_op_state_set(fm, FM_STA_STOP);
1109 FM_UNLOCK(fm_ops_lock);
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.
1119 fm_s32 fm_is_dese_chan(struct fm *pfm, fm_u16 freq)
1123 if (fm_low_ops.bi.is_dese_chan)
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);
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.
1139 fm_s32 fm_desense_check(struct fm *pfm, fm_u16 freq,fm_s32 rssi)
1143 if (fm_low_ops.bi.desense_check)
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);
1152 fm_s32 fm_dump_reg(void)
1155 if (fm_low_ops.bi.dumpreg)
1157 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1158 ret = fm_low_ops.bi.dumpreg();
1159 FM_UNLOCK(fm_ops_lock);
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.
1169 fm_s32 fm_get_hw_info(struct fm *pfm, struct fm_hw_info *req)
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;
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);
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.
1198 fm_s32 fm_get_i2s_info(struct fm *pfm, struct fm_i2s_info *req)
1202 if (fm_low_ops.bi.i2s_get) {
1203 return fm_low_ops.bi.i2s_get(&req->status, &req->mode, &req->rate);
1205 req->status = fm_i2s_inf.status;
1206 req->mode = fm_i2s_inf.mode;
1207 req->rate = fm_i2s_inf.rate;
1214 fm_s32 fm_hwscan_stop(struct fm *fm)
1218 if ((FM_STA_SCAN != fm_op_state_get(fm))&&(FM_STA_SEEK!=fm_op_state_get(fm)))
1220 WCN_DBG(FM_WAR | MAIN, "fm isn't on scan, no need stop\n");
1224 FMR_ASSERT(fm_low_ops.bi.scanstop);
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");
1231 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1233 fm_low_ops.bi.rampdown();
1234 fm_low_ops.bi.setfreq(fm_cur_freq_get());
1236 FM_UNLOCK(fm_ops_lock);
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
1246 fm_s32 fm_ana_switch(struct fm *fm, fm_s32 antenna)
1250 FMR_ASSERT(fm_low_ops.bi.anaswitch);
1251 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
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);
1258 WCN_DBG(FM_ALT | MAIN, "Switch ana Failed\n");
1260 WCN_DBG(FM_DBG | MAIN, "Switch ana OK!\n");
1263 FM_UNLOCK(fm_ops_lock);
1268 fm_s32 fm_setvol(struct fm *fm, fm_u32 vol)
1272 if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) {
1275 FMR_ASSERT(fm_low_ops.bi.volset);
1276 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1278 tmp_vol = (vol > 15) ? 15 : vol;
1279 fm_low_ops.bi.volset(tmp_vol);
1280 fm->vol = (fm_s32)tmp_vol;
1282 FM_UNLOCK(fm_ops_lock);
1286 fm_s32 fm_getvol(struct fm *fm, fm_u32 *vol)
1290 if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) {
1293 FMR_ASSERT(fm_low_ops.bi.volget);
1294 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1296 fm_low_ops.bi.volget(&tmp_vol);
1297 *vol = (fm_u32)tmp_vol;
1299 FM_UNLOCK(fm_ops_lock);
1303 fm_s32 fm_mute(struct fm *fm, fm_u32 bmute)
1307 if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) {
1311 FMR_ASSERT(fm_low_ops.bi.mute);
1312 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1315 ret = fm_low_ops.bi.mute(fm_true);
1318 ret = fm_low_ops.bi.mute(fm_false);
1319 fm->mute = fm_false;
1322 FM_UNLOCK(fm_ops_lock);
1326 fm_s32 fm_getrssi(struct fm *fm, fm_s32 *rssi)
1330 if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) {
1334 FMR_ASSERT(fm_low_ops.bi.rssiget);
1335 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1337 ret = fm_low_ops.bi.rssiget(rssi);
1339 FM_UNLOCK(fm_ops_lock);
1343 fm_s32 fm_reg_read(struct fm *fm, fm_u8 addr, fm_u16 *val)
1347 FMR_ASSERT(fm_low_ops.bi.read);
1348 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1350 ret = fm_low_ops.bi.read(addr, val);
1352 FM_UNLOCK(fm_ops_lock);
1356 fm_s32 fm_reg_write(struct fm *fm, fm_u8 addr, fm_u16 val)
1360 FMR_ASSERT(fm_low_ops.bi.write);
1361 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1363 ret = fm_low_ops.bi.write(addr, val);
1365 FM_UNLOCK(fm_ops_lock);
1369 fm_s32 fm_chipid_get(struct fm *fm, fm_u16 *chipid)
1372 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1374 *chipid = fm->chip_id;
1376 FM_UNLOCK(fm_ops_lock);
1380 fm_s32 fm_monostereo_get(struct fm *fm, fm_u16 *ms)
1384 FMR_ASSERT(fm_low_ops.bi.msget);
1386 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1388 if (fm_low_ops.bi.msget(ms) == fm_false) {
1392 FM_UNLOCK(fm_ops_lock);
1397 * Force set to stero/mono mode
1398 * @MonoStereo -- 0, auto; 1, mono
1399 * If success, return 0; else error code
1401 fm_s32 fm_monostereo_set(struct fm *fm, fm_s32 ms)
1405 FMR_ASSERT(fm_low_ops.bi.msset);
1406 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1408 ret = fm_low_ops.bi.msset(ms);
1410 FM_UNLOCK(fm_ops_lock);
1414 fm_s32 fm_pamd_get(struct fm *fm, fm_u16 *pamd)
1418 FMR_ASSERT(fm_low_ops.bi.pamdget);
1420 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1422 if (fm_low_ops.bi.pamdget(pamd) == fm_false) {
1426 FM_UNLOCK(fm_ops_lock);
1430 fm_s32 fm_caparray_get(struct fm *fm, fm_s32 *ca)
1434 FMR_ASSERT(fm_low_ops.bi.caparray_get);
1436 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1438 ret = fm_low_ops.bi.caparray_get(ca);
1440 FM_UNLOCK(fm_ops_lock);
1444 fm_s32 fm_em_test(struct fm *fm, fm_u16 group, fm_u16 item, fm_u32 val)
1448 FMR_ASSERT(fm_low_ops.bi.em);
1449 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1451 if (fm_false == fm_low_ops.bi.em(group, item, val)) {
1455 FM_UNLOCK(fm_ops_lock);
1459 fm_s32 fm_rds_tx(struct fm *fm, struct fm_rds_tx_parm *parm)
1463 FMR_ASSERT(fm_low_ops.ri.rds_tx);
1464 FMR_ASSERT(fm_low_ops.ri.rds_tx_enable);
1466 if (fm_pwr_state_get(fm) != FM_PWR_TX_ON) {
1467 parm->err = FM_BADSTATUS;
1471 if(parm->other_rds_cnt > 29)
1473 parm->err = FM_EPARM;
1474 WCN_DBG(FM_ERR | MAIN,"other_rds_cnt=%d\n",parm->other_rds_cnt);
1479 ret = fm_low_ops.ri.rds_tx_enable();
1481 WCN_DBG(FM_ERR | MAIN,"Rds_Tx_Enable failed!\n");
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);
1487 WCN_DBG(FM_ERR | MAIN,"Rds_Tx failed!\n");
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;
1499 fm_s32 fm_rds_onoff(struct fm *fm, fm_u16 rdson_off)
1503 FMR_ASSERT(fm_low_ops.ri.rds_onoff);
1504 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
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");
1514 fm_enable_rds_BlerCheck(fm);
1516 fm->rds_on = fm_false;
1517 fm_disable_rds_BlerCheck();
1518 fm_low_ops.ri.rds_onoff(fm->pstRDSData, fm_false);
1522 FM_UNLOCK(fm_ops_lock);
1526 fm_s32 fm_rds_good_bc_get(struct fm *fm, fm_u16 *gbc)
1530 FMR_ASSERT(fm_low_ops.ri.rds_gbc_get);
1532 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1534 *gbc = fm_low_ops.ri.rds_gbc_get();
1536 FM_UNLOCK(fm_ops_lock);
1540 fm_s32 fm_rds_bad_bc_get(struct fm *fm, fm_u16 *bbc)
1544 FMR_ASSERT(fm_low_ops.ri.rds_bbc_get);
1546 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1548 *bbc = fm_low_ops.ri.rds_bbc_get();
1550 FM_UNLOCK(fm_ops_lock);
1554 fm_s32 fm_rds_bler_ratio_get(struct fm *fm, fm_u16 *bbr)
1558 FMR_ASSERT(fm_low_ops.ri.rds_bbr_get);
1560 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1562 *bbr = (fm_u16)fm_low_ops.ri.rds_bbr_get();
1564 FM_UNLOCK(fm_ops_lock);
1568 fm_s32 fm_rds_group_cnt_get(struct fm *fm, struct rds_group_cnt_t *dst)
1572 FMR_ASSERT(fm_low_ops.ri.rds_gc_get);
1574 if (FM_LOCK(fm_rds_cnt)) return (-FM_ELOCK);
1576 ret = fm_low_ops.ri.rds_gc_get(dst, fm->pstRDSData);
1578 FM_UNLOCK(fm_rds_cnt);
1582 fm_s32 fm_rds_group_cnt_reset(struct fm *fm)
1586 FMR_ASSERT(fm_low_ops.ri.rds_gc_reset);
1587 if (FM_LOCK(fm_rds_cnt)) return (-FM_ELOCK);
1589 ret = fm_low_ops.ri.rds_gc_reset(fm->pstRDSData);
1591 FM_UNLOCK(fm_rds_cnt);
1595 fm_s32 fm_rds_log_get(struct fm *fm, struct rds_rx_t *dst, fm_s32 *dst_len)
1599 FMR_ASSERT(fm_low_ops.ri.rds_log_get);
1601 FMR_ASSERT(dst_len);
1602 if (FM_LOCK(fm_read_lock)) return (-FM_ELOCK);
1604 ret = fm_low_ops.ri.rds_log_get(dst, dst_len);
1606 FM_UNLOCK(fm_read_lock);
1610 fm_s32 fm_rds_block_cnt_reset(struct fm *fm)
1614 FMR_ASSERT(fm_low_ops.ri.rds_bc_reset);
1615 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1617 ret = fm_low_ops.ri.rds_bc_reset();
1619 FM_UNLOCK(fm_ops_lock);
1623 fm_s32 fm_i2s_set(struct fm *fm, fm_s32 onoff, fm_s32 mode, fm_s32 sample)
1627 FMR_ASSERT(fm_low_ops.bi.i2s_set);
1628 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1630 ret = fm_low_ops.bi.i2s_set(onoff, mode, sample);
1632 FM_UNLOCK(fm_ops_lock);
1639 fm_s32 fm_tune_tx(struct fm *fm, struct fm_tune_parm *parm)
1643 FMR_ASSERT(fm_low_ops.bi.tune_tx);
1645 if (fm_pwr_state_get(fm) != FM_PWR_TX_ON) {
1646 parm->err = FM_BADSTATUS;
1649 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1651 WCN_DBG(FM_DBG | MAIN, "%s\n", __func__);
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
1657 if((ret = MT6620_RampDown_Tx()))
1661 //tune to desired channel
1662 if (fm_true != fm_low_ops.bi.tune_tx(parm->freq))
1664 parm->err = FM_TUNE_FAILED;
1665 WCN_DBG(FM_ALT | MAIN, "Tx tune failed\n");
1668 fm_op_state_set(fm, FM_STA_PLAY);
1669 FM_UNLOCK(fm_ops_lock);
1677 fm_s32 fm_tune(struct fm *fm, struct fm_tune_parm *parm)
1681 FMR_ASSERT(fm_low_ops.bi.mute);
1682 FMR_ASSERT(fm_low_ops.bi.rampdown);
1683 FMR_ASSERT(fm_low_ops.bi.setfreq);
1685 if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
1687 WCN_DBG(FM_DBG | MAIN, "%s\n", __func__);
1689 if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) {
1690 parm->err = FM_BADSTATUS;
1695 // fm_low_ops.bi.mute(fm_true);
1696 fm_low_ops.bi.rampdown();
1698 if (fm_cur_freq_get() != parm->freq) {
1699 fm_memset(fm->pstRDSData, 0, sizeof(rds_t));
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) {
1709 WCN_DBG(FM_INF | MAIN, "HILO side %d\n", ret);
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) {
1718 WCN_DBG(FM_INF | MAIN, "FA %d\n", ret);
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) {
1727 WCN_DBG(FM_INF | MAIN, "MCU %d\n", ret);
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) {
1736 WCN_DBG(FM_INF | MAIN, "GPS %d\n", ret);
1739 fm_op_state_set(fm, FM_STA_TUNE);
1740 WCN_DBG(FM_ALT | MAIN, "tuning to %d\n", parm->freq);
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");
1748 // fm_low_ops.bi.mute(fm_false);
1749 fm_op_state_set(fm, FM_STA_PLAY);
1751 FM_UNLOCK(fm_ops_lock);
1754 //cqi log tool entry
1755 fm_s32 fm_cqi_log(void)
1759 FMR_ASSERT(fm_low_ops.bi.cqi_log);
1760 freq = fm_cur_freq_get();
1761 if (0 == fm_get_channel_space(freq)) {
1764 if((freq != 10000) && (0xffffffff != g_dbg_level))
1768 if (FM_LOCK(fm_ops_lock))
1770 ret = fm_low_ops.bi.cqi_log(8750,10800,2,5);
1771 FM_UNLOCK(fm_ops_lock);
1774 /*fm soft mute tune function*/
1775 fm_s32 fm_soft_mute_tune(struct fm *fm, struct fm_softmute_tune_t *parm)
1779 FMR_ASSERT(fm_low_ops.bi.softmute_tune);
1781 if (FM_LOCK(fm_ops_lock))
1785 if (fm_pwr_state_get(fm) != FM_PWR_RX_ON)
1787 parm->valid = fm_false;
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);
1796 if (fm_false == fm_low_ops.bi.softmute_tune(parm->freq,&parm->rssi,&parm->valid))
1798 parm->valid = fm_false;
1799 WCN_DBG(FM_ALT | MAIN, "sm tune failed\n");
1803 // fm_low_ops.bi.mute(fm_false);
1805 WCN_DBG(FM_NTC | MAIN, "-%s()\n", __func__);
1806 FM_UNLOCK(fm_ops_lock);
1810 fm_s32 fm_over_bt(struct fm *fm, fm_s32 flag)
1813 FMR_ASSERT(fm_low_ops.bi.fm_via_bt);
1815 if (fm_pwr_state_get(fm) != FM_PWR_RX_ON)
1819 if (FM_LOCK(fm_ops_lock))
1822 ret = fm_low_ops.bi.fm_via_bt(flag);
1825 WCN_DBG(FM_ALT | MAIN,"%s(),failed!\n", __func__);
1831 WCN_DBG(FM_NTC | MAIN,"%s(),[ret=%d]!\n", __func__, ret);
1832 FM_UNLOCK(fm_ops_lock);
1835 fm_s32 fm_tx_support(struct fm *fm, fm_s32 *support)
1837 if (FM_LOCK(fm_ops_lock))
1839 if(fm_low_ops.bi.tx_support)
1841 fm_low_ops.bi.tx_support(support);
1847 WCN_DBG(FM_NTC | MAIN,"%s(),[%d]!\n", __func__, *support);
1848 FM_UNLOCK(fm_ops_lock);
1851 fm_s32 fm_rdstx_support(struct fm *fm, fm_s32 *support)
1853 if (FM_LOCK(fm_ops_lock))
1855 if(fm_low_ops.ri.rdstx_support)
1857 fm_low_ops.ri.rdstx_support(support);
1863 WCN_DBG(FM_NTC | MAIN,"support=[%d]!\n", *support);
1864 FM_UNLOCK(fm_ops_lock);
1867 fm_s32 fm_rdstx_enable(struct fm *fm, fm_s32 *support)
1869 if (FM_LOCK(fm_ops_lock))
1879 WCN_DBG(FM_NTC | MAIN,"rds tx enable=[%d]!\n", *support);
1880 FM_UNLOCK(fm_ops_lock);
1884 static void fm_timer_func(unsigned long data)
1886 struct fm *fm = g_fm_struct;
1888 if (FM_LOCK(fm_timer_lock)) return;
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
1896 WCN_DBG(FM_NTC | MAIN, "timer:rds_wk\n");
1897 fm->timer_wkthd->add_work(fm->timer_wkthd, fm->rds_wk);
1901 FM_UNLOCK(fm_timer_lock);
1905 static void fmtx_timer_func(unsigned long data)
1907 struct fm *fm = g_fm_struct;
1908 fm_s32 vco_cycle = 1;
1910 if (FM_LOCK(fm_timer_lock)) return;
1912 fm_timer_sys->count++;
1915 //schedule tx pwr ctrl work if need
1916 if(fm->txpwrctl < 1)
1918 WCN_DBG(FM_WAR | MAIN,"tx power ctl time err\n");
1919 fm->txpwrctl = FM_TX_PWR_CTRL_INVAL_MIN;
1921 if((fm_timer_sys->tx_pwr_ctrl_en == FM_TX_PWR_CTRL_ENABLE) && (fm_timer_sys->count%fm->txpwrctl == 0))
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);
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);
1932 //schedule tx desense with wifi/bt work if need
1935 WCN_DBG(FM_WAR | MAIN,"tx vco tracking time err\n");
1936 fm->vcooff = FM_TX_VCO_OFF_MIN;
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))
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);
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
1951 FM_UNLOCK(fm_timer_lock);
1954 static void fm_tx_power_ctrl_worker_func(unsigned long data)
1956 fm_s32 ctrl = 0,ret=0;
1957 struct fm *fm = g_fm_struct;
1959 WCN_DBG(FM_NTC | MAIN,"+%s():\n", __func__);
1961 if(fm_low_ops.bi.tx_pwr_ctrl == NULL)
1963 if (FM_LOCK(fm_rxtx_lock)) return;
1965 if(fm_pwr_state_get(fm) != FM_PWR_TX_ON){
1966 WCN_DBG(FM_ERR | MAIN,"FM is not on TX mode\n");
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);
1975 WCN_DBG(FM_ERR | MAIN,"tx_pwr_ctrl fail\n");
1979 FM_UNLOCK(fm_rxtx_lock);
1980 WCN_DBG(FM_NTC | MAIN,"-%s()\n", __func__);
1983 static void fm_tx_rtc_ctrl_worker_func(unsigned long data)
1987 struct fm_gps_rtc_info rtcInfo;
1988 //struct timeval curTime;
1989 //struct fm *fm = (struct fm*)fm_cb;
1990 unsigned long curTime = 0;
1992 WCN_DBG(FM_NTC | MAIN,"+%s():\n", __func__);
1994 if(FM_LOCK(fm_rtc_mutex)) return;
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);
2001 WCN_DBG(FM_NTC | MAIN,"there's no new rtc drift info\n");
2002 FM_UNLOCK(fm_rtc_mutex);
2006 if(rtcInfo.age > rtcInfo.ageThd){
2007 WCN_DBG(FM_WAR | MAIN,"age over it's threshlod\n");
2010 if((rtcInfo.drift <= rtcInfo.driftThd) && (rtcInfo.drift >= -rtcInfo.driftThd)){
2011 WCN_DBG(FM_WAR | MAIN,"drift over it's MIN threshlod\n");
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;
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;
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");
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");
2036 if(fm_low_ops.bi.rtc_drift_ctrl != NULL)
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)))
2044 WCN_DBG(FM_NTC | MAIN,"-%s()\n", __func__);
2048 static void fm_tx_desense_wifi_worker_func(unsigned long data)
2052 struct fm *fm = g_fm_struct;
2054 WCN_DBG(FM_NTC | MAIN,"+%s():\n", __func__);
2056 if (FM_LOCK(fm_rxtx_lock)) return;
2058 if(fm_pwr_state_get(fm) != FM_PWR_TX_ON){
2059 WCN_DBG(FM_ERR | MAIN,"FM is not on TX mode\n");
2063 fm_tx_rtc_ctrl_worker_func(0);
2066 if(fm_low_ops.bi.tx_desense_wifi)
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);
2072 WCN_DBG(FM_ERR | MAIN,"tx_desense_wifi fail\n");
2076 FM_UNLOCK(fm_rxtx_lock);
2077 WCN_DBG(FM_NTC | MAIN,"-%s()\n", __func__);
2082 ************************************************************************************
2083 Function: fm_get_gps_rtc_info()
2085 Description: get GPS RTC drift info, and this function should not block
2089 Return Value: success:0, failed: error coe
2090 ************************************************************************************
2092 fm_s32 fm_get_gps_rtc_info(struct fm_gps_rtc_info *src)
2095 // fm_s32 retry_cnt = 0;
2096 struct fm_gps_rtc_info *dst=&gps_rtc_info;
2101 if(src->retryCnt > 0){
2102 dst->retryCnt = src->retryCnt;
2103 WCN_DBG(FM_NTC | MAIN,"%s, new [retryCnt=%d]\n", __func__, dst->retryCnt);
2105 if(src->ageThd > 0){
2106 dst->ageThd = src->ageThd;
2107 WCN_DBG(FM_NTC | MAIN,"%s, new [ageThd=%d]\n", __func__, dst->ageThd);
2109 if(src->driftThd > 0){
2110 dst->driftThd = src->driftThd;
2111 WCN_DBG(FM_NTC | MAIN,"%s, new [driftThd=%d]\n", __func__, dst->driftThd);
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);
2117 ret = fm_rtc_mutex->trylock(fm_rtc_mutex,dst->retryCnt);
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;
2127 FM_UNLOCK(fm_rtc_mutex);
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);
2141 static void fm_enable_rds_BlerCheck(struct fm *fm)
2143 if (FM_LOCK(fm_timer_lock)) return;
2144 fm_timer_sys->start(fm_timer_sys);
2145 FM_UNLOCK(fm_timer_lock);
2148 static void fm_disable_rds_BlerCheck(void)
2150 if (FM_LOCK(fm_timer_lock)) return;
2151 fm_timer_sys->stop(fm_timer_sys);
2152 FM_UNLOCK(fm_timer_lock);
2155 void fm_rds_reset_work_func(unsigned long data)
2159 if (!fm_low_ops.ri.rds_blercheck) {
2162 if (FM_LOCK(fm_rxtx_lock)) return;
2164 if (FM_LOCK(fm_rds_cnt)) return;
2165 ret = fm_low_ops.ri.rds_blercheck(g_fm_struct->pstRDSData);
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
2170 g_fm_struct->pstRDSData->event_status |= RDS_EVENT_AF;
2172 if (!ret && g_fm_struct->pstRDSData->event_status)
2174 FM_EVENT_SEND(g_fm_struct->rds_event, FM_RDS_DATA_READY);
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);
2182 void fm_subsys_reset_work_func(unsigned long data)
2184 g_dbg_level = 0xffffffff;
2185 if (FM_LOCK(fm_ops_lock)) return;
2187 fm_sys_state_set(g_fm_struct, FM_SUBSYS_RST_START);
2189 if (g_fm_struct->chipon == fm_false)
2191 WCN_DBG(FM_ALT | MAIN, "no need do recover\n");
2194 // subsystem power off
2195 fm_low_ops.bi.pwroff(0);
2200 fm_low_ops.bi.msdelay(2000);
2202 // subsystem power on
2203 fm_low_ops.bi.pwron(0);
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");
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);
2215 WCN_DBG(FM_ALT | MAIN, "no need do re-powerup\n");
2219 fm_low_ops.bi.anaswitch(g_fm_struct->ana_type);
2221 fm_low_ops.bi.setfreq(fm_cur_freq_get());
2223 fm_low_ops.bi.volset((fm_u8)g_fm_struct->vol);
2225 fm_low_ops.bi.mute(g_fm_struct->mute);
2227 fm_low_ops.ri.rds_onoff(g_fm_struct->pstRDSData, g_fm_struct->rds_on);
2229 WCN_DBG(FM_ALT | MAIN, "recover done\n");
2232 fm_sys_state_set(g_fm_struct, FM_SUBSYS_RST_END);
2233 fm_sys_state_set(g_fm_struct, FM_SUBSYS_RST_OFF);
2235 FM_UNLOCK(fm_ops_lock);
2236 g_dbg_level = 0xfffffff5;
2239 static void fm_eint_handler(void)
2241 struct fm *fm = g_fm_struct;
2242 WCN_DBG(FM_DBG | MAIN, "intr occur, ticks:%d\n", jiffies_to_msecs(jiffies));
2245 fm->eint_wkthd->add_work(fm->eint_wkthd, fm->eint_wk);
2249 static fm_s32 fm_rds_parser(struct rds_rx_t *rds_raw, fm_s32 rds_size)
2251 struct fm *fm = g_fm_struct;//(struct fm *)work->data;
2252 rds_t *pstRDSData = fm->pstRDSData;
2254 if (FM_LOCK(fm_read_lock)) return (-FM_ELOCK);
2256 fm_low_ops.ri.rds_parser(pstRDSData, rds_raw, rds_size, fm_cur_freq_get);
2257 FM_UNLOCK(fm_read_lock);
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);
2267 static void fm_eint_work_func(unsigned long data)
2269 fm_event_parser(fm_rds_parser);
2270 //re-enable eint if need
2274 static fm_s32 fm_callback_register(struct fm_lowlevel_ops *ops)
2278 ops->cb.cur_freq_get = fm_cur_freq_get;
2279 ops->cb.cur_freq_set = fm_cur_freq_set;
2283 static fm_s32 fm_callback_unregister(struct fm_lowlevel_ops *ops)
2287 fm_memset(&ops->cb, 0, sizeof(struct fm_callback));
2292 static fm_s32 fm_para_init(struct fm *fmp)
2296 fmp->band = FM_BAND_SPECIAL;
2297 fmp->min_freq = FM_RX_BAND_FREQ_L;
2298 fmp->max_freq = FM_RX_BAND_FREQ_H;
2304 fm_s32 fm_cust_config_setup(fm_s8 * filename)
2307 #if (defined(MT6620_FM)||defined(MT6628_FM))
2309 ret = MT6628fm_cust_config_setup(filename);
2312 WCN_DBG(FM_ERR | MAIN, "MT6628fm_cust_config_setup failed\n");
2316 ret = MT6620fm_cust_config_setup(filename);
2319 WCN_DBG(FM_ERR | MAIN, "MT6620fm_cust_config_setup failed\n");
2323 fm_cust_config(filename);
2326 WCN_DBG(FM_ERR | MAIN, "fm_cust_config failed\n");
2332 struct fm* fm_dev_init(fm_u32 arg)
2335 struct fm *fm = NULL;
2337 // if (!fm_low_ops.ri.rds_bci_get)
2340 // if (!fm_low_ops.bi.chipid_get)
2343 //alloc fm main data structure
2344 if (!(fm = fm_zalloc(sizeof(struct fm)))) {
2345 WCN_DBG(FM_ALT | MAIN, "-ENOMEM\n");
2351 fm->chipon = fm_false;
2352 fm_pwr_state_set(fm, FM_PWR_OFF);
2353 // fm->chip_id = fm_low_ops.bi.chipid_get();
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;
2370 if (!(fm->rds_event = fm_flag_event_create("fm_rds_event"))) {
2371 WCN_DBG(FM_ALT | MAIN, "-ENOMEM for RDS event\n");
2376 fm_flag_event_get(fm->rds_event);
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");
2387 fm->timer_wkthd = fm_workthread_create("fm_timer_wq");
2389 if (!fm->timer_wkthd) {
2390 WCN_DBG(FM_ALT | MAIN, "-ENOMEM for fm_timer_wq\n");
2395 fm_workthread_get(fm->timer_wkthd);
2397 fm->eint_wkthd = fm_workthread_create("fm_eint_wq");
2399 if (!fm->eint_wkthd) {
2400 WCN_DBG(FM_ALT | MAIN, "-ENOMEM for fm_eint_wq\n");
2405 fm_workthread_get(fm->eint_wkthd);
2407 fm->eint_wk = fm_work_create("fm_eint_work");
2410 WCN_DBG(FM_ALT | MAIN, "-ENOMEM for eint_wk\n");
2414 fm_work_get(fm->eint_wk);
2415 fm->eint_wk->init(fm->eint_wk, fm_eint_work_func, (unsigned long)fm);
2418 // create reset work
2419 fm->rst_wk = fm_work_create("fm_rst_work");
2422 WCN_DBG(FM_ALT | MAIN, "-ENOMEM for rst_wk\n");
2426 fm_work_get(fm->rst_wk);
2427 fm->rst_wk->init(fm->rst_wk, fm_subsys_reset_work_func, (unsigned long)fm);
2430 fm->rds_wk = fm_work_create("fm_rds_work");
2432 WCN_DBG(FM_ALT | MAIN, "-ENOMEM for rds_wk\n");
2436 fm_work_get(fm->rds_wk);
2437 fm->rds_wk->init(fm->rds_wk, fm_rds_reset_work_func, (unsigned long)fm);
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");
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);
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");
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);
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);
2464 //init customer config parameter
2465 fm_cust_config_setup(NULL);
2473 if (fm->eint_wkthd) {
2474 ret = fm_workthread_put(fm->eint_wkthd);
2477 fm->eint_wkthd = NULL;
2480 if (fm->timer_wkthd) {
2481 ret = fm_workthread_put(fm->timer_wkthd);
2484 fm->timer_wkthd = NULL;
2488 ret = fm_work_put(fm->eint_wk);
2495 ret = fm_work_put(fm->rds_wk);
2502 ret = fm_work_put(fm->rst_wk);
2508 if (fm->fm_tx_desense_wifi_work) {
2509 ret = fm_work_put(fm->fm_tx_desense_wifi_work);
2512 fm->fm_tx_desense_wifi_work = NULL;
2515 if (fm->fm_tx_power_ctrl_work) {
2516 ret = fm_work_put(fm->fm_tx_power_ctrl_work);
2519 fm->fm_tx_power_ctrl_work = NULL;
2522 if (fm->pstRDSData) {
2523 fm_free(fm->pstRDSData);
2524 fm->pstRDSData = NULL;
2532 fm_s32 fm_dev_destroy(struct fm *fm)
2536 WCN_DBG(FM_DBG | MAIN, "%s\n", __func__);
2538 fm_timer_sys->stop(fm_timer_sys);
2540 if (fm->eint_wkthd) {
2541 ret = fm_workthread_put(fm->eint_wkthd);
2544 fm->eint_wkthd = NULL;
2547 if (fm->timer_wkthd) {
2548 ret = fm_workthread_put(fm->timer_wkthd);
2551 fm->timer_wkthd = NULL;
2555 ret = fm_work_put(fm->eint_wk);
2562 ret = fm_work_put(fm->rds_wk);
2569 ret = fm_work_put(fm->rst_wk);
2575 if (fm->pstRDSData) {
2576 fm_free(fm->pstRDSData);
2577 fm->pstRDSData = NULL;
2580 if (fm->pstRDSData) {
2581 fm_free(fm->pstRDSData);
2582 fm->pstRDSData = NULL;
2585 fm_flag_event_put(fm->rds_event);
2597 fm_s32 fm_env_setup(void)
2601 WCN_DBG(FM_NTC | MAIN, "%s\n", __func__);
2602 #if (defined(MT6620_FM)||defined(MT6628_FM))
2604 //register call back functions
2605 ret = fm_callback_register(&MT6620fm_low_ops);
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);
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);
2621 WCN_DBG(FM_NTC | MAIN, "3. fm rds ops registered\n");
2624 //register call back functions
2625 ret = fm_callback_register(&MT6628fm_low_ops);
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);
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);
2641 WCN_DBG(FM_NTC | MAIN, "3. fm rds ops registered\n");
2644 //register call back functions
2645 ret = fm_callback_register(&fm_low_ops);
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);
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);
2664 WCN_DBG(FM_NTC | MAIN, "3. fm rds ops registered\n");
2667 fm_ops_lock = fm_lock_create("ops_lock");
2673 fm_read_lock = fm_lock_create("rds_read");
2675 if (!fm_read_lock) {
2679 fm_rds_cnt = fm_lock_create("rds_cnt");
2685 fm_timer_lock = fm_spin_lock_create("timer_lock");
2687 if (!fm_timer_lock) {
2690 fm_rxtx_lock = fm_lock_create("rxtx_lock");
2691 if (!fm_rxtx_lock) {
2694 fm_rtc_mutex = fm_lock_create("rxtx_lock");
2695 if (!fm_rxtx_lock) {
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");
2706 fm_timer_sys = fm_timer_create("fm_sys_timer");
2708 if (!fm_timer_sys) {
2712 fm_timer_get(fm_timer_sys);
2713 WCN_DBG(FM_NTC | MAIN, "5. fm timer created\n");
2715 ret = fm_link_setup((void*)fm_wholechip_rst_cb);
2718 WCN_DBG(FM_ERR | MAIN, "fm link setup Failed\n");
2725 fm_s32 fm_env_destroy(void)
2729 WCN_DBG(FM_NTC | MAIN, "%s\n", __func__);
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);
2741 //put low level functions
2742 ret = MT6620fm_low_ops_unregister(&MT6620fm_low_ops);
2749 ret = MT6620fm_rds_ops_unregister(&MT6620fm_low_ops);
2755 #if defined(MT6628_FM)
2756 //register call back functions
2757 ret = fm_callback_unregister(&MT6628fm_low_ops);
2762 //put low level functions
2763 ret = MT6628fm_low_ops_unregister(&MT6628fm_low_ops);
2770 ret = MT6628fm_rds_ops_unregister(&MT6628fm_low_ops);
2777 //register call back functions
2778 ret = fm_callback_unregister(&fm_low_ops);
2783 //put low level functions
2784 ret = fm_low_ops_unregister(&fm_low_ops);
2791 ret = fm_rds_ops_unregister(&fm_low_ops);
2797 ret = fm_lock_put(fm_ops_lock);
2802 ret = fm_lock_put(fm_read_lock);
2805 fm_read_lock = NULL;
2807 ret = fm_lock_put(fm_rds_cnt);
2811 ret = fm_spin_lock_put(fm_timer_lock);
2814 fm_timer_lock = NULL;
2816 ret = fm_timer_put(fm_timer_sys);
2819 fm_timer_sys = NULL;
2824 #if 0//(!defined(MT6620_FM)&&!defined(MT6628_FM))
2825 fm_s32 fm_priv_register(struct fm_priv *pri, struct fm_pub *pub)
2830 WCN_DBG(FM_NTC | MAIN, "%s\n", __func__);
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;
2844 // for special chip(chip with DSP) use
2845 fm_low_ops.cb.chan_para_get = priv_adv.priv_tbl.chan_para_get;
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;
2861 fm_s32 fm_priv_unregister(struct fm_priv *pri, struct fm_pub *pub)
2863 WCN_DBG(FM_NTC | MAIN, "%s\n", __func__);
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));
2877 * GetChannelSpace - get the spcace of gived channel
2878 * @freq - value in 760~1080 or 7600~10800
2880 * Return 0, if 760~1080; return 1, if 7600 ~ 10800, else err code < 0
2882 fm_s32 fm_get_channel_space(fm_s32 freq)
2884 if ((freq >= 760) && (freq <= 1080)) {
2886 } else if ((freq >= 7600) && (freq <= 10800)) {