support different wifi bt chip auto compatible
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rda5990 / drv_fm_rda / RDA5990_FM_drv_gpio.c
1 #include <linux/module.h>
2 #include <linux/kernel.h>
3 #include <linux/init.h>
4 #include <linux/delay.h> // udelay()
5 #include <linux/device.h> // device_create()
6 #include <linux/platform_device.h>
7 #include <linux/i2c.h>
8 #include <linux/cdev.h>
9 #include <linux/fs.h>
10 #include <linux/version.h>      /* constant of kernel version */
11 #include <asm/uaccess.h> // get_user()
12
13 #include <linux/fm.h>
14 #include <mach/mt6575_gpio.h>
15 #include <mach/mtk_rtc.h>
16 #include <linux/proc_fs.h>
17 #include <linux/string.h>
18 #include <linux/delay.h>
19
20 // if need debug, define FMDEBUG
21 //#define FMDEBUG
22
23 // if your platform is MT6515/6575, define MTK_MT6515 
24 #define MTK_MT6515
25
26 // if your platform is MT6515/6575 and MTK FM is MT6626, define MT6626 
27 //#define MT6626
28
29 #define FM_ALERT(f, s...) \
30         do { \
31                 printk(KERN_ALERT "RDAFM " f, ## s); \
32         } while(0)
33
34 #ifdef FMDEBUG
35 #define FM_DEBUG(f, s...) \
36         do { \
37                 printk("RDAFM " f, ## s); \
38         } while(0)
39 #else
40 #define FM_DEBUG(f, s...)
41 #endif
42
43 #define RDA599X_SCANTBL_SIZE  16 //16*uinit16_t
44 #define RDA599X_FM_SCAN_UP       0x0
45 #define RDA599X_FM_SCAN_DOWN     0x01
46
47 extern int rda_gpio_i2c_read_1_addr_2_data(uint8_t chipAddr, uint8_t regAddr, unsigned short *buffer);
48 extern int rda_gpio_i2c_write_1_addr_2_data(uint8_t chipAddr, uint8_t regAddr, unsigned short data);
49 extern int rda_fm_power_off(void);
50 extern int rda_fm_power_on(void);
51
52 /******************************************************************************
53  * CONSTANT DEFINITIONS
54  *****************************************************************************/
55 #define RDAFM_SLAVE_ADDR        0x11    //RDA FM Chip address
56
57 #define RDAFM_MASK_RSSI         0X7F // RSSI
58
59
60
61 #define ID_RDA5802E             0x5804
62 #define ID_RDA5802H             0x5801
63 #define ID_RDA5802N             0x5808
64 #define ID_RDA5820              0x5805
65 #define ID_RDA5820NS            0x5820
66
67
68
69 static struct proc_dir_entry *g_fm_proc = NULL;
70 static struct fm *g_fm_struct = NULL;
71 static atomic_t scan_complete_flag;
72
73 #define FM_PROC_FILE "fm"
74
75 /******************************************************************************
76  * STRUCTURE DEFINITIONS
77  *****************************************************************************/
78
79 enum RDAFM_CHIP_TYPE {
80         CHIP_TYPE_RDA5802E = 0,
81         CHIP_TYPE_RDA5802H,
82         CHIP_TYPE_RDA5802N,
83         CHIP_TYPE_RDA5820,
84         CHIP_TYPE_RDA5820NS,
85 };
86
87
88 typedef struct
89 {
90         uint8_t         address;
91         uint16_t        value;
92 }RDA_FM_REG_T;   
93
94 typedef struct
95 {
96         bool            byPowerUp;
97         struct fm_tune_parm parm
98 }FM_TUNE_T;
99 static FM_TUNE_T fm_tune_data = {false, {}};
100
101 typedef enum
102 {
103         FM_RECEIVER,                            //5800,5802,5804
104         FM_TRANSMITTER,                 //5820
105 }RDA_RADIO_WORK_E;
106
107 typedef enum
108 {
109         OFF,
110         ON,
111 }RDA_FM_POWER_STATE_T;
112
113 struct fm {
114         uint32_t ref;
115         bool powerup;
116         uint16_t chip_id;
117         //    uint16_t device_id;
118         uint8_t chipAddr;
119         dev_t dev_t;
120         uint16_t min_freq; // KHz
121         uint16_t max_freq; // KHz
122         uint8_t band;   // TODO
123         struct class *cls;
124         struct device *dev;
125         struct cdev cdev;
126         //    struct i2c_client *i2c_client;
127 };
128
129
130
131
132 /******************************************************************************
133  * FUNCTION PROTOTYPES
134  *****************************************************************************/
135
136
137 static int RDAFM_clear_hmute(uint8_t chipAddr);
138 static int RDAFM_enable_hmute(uint8_t chipAddr);
139 static bool RDAFM_Scan(uint8_t chipAddr,
140                 uint16_t min_freq, uint16_t max_freq,
141                 uint16_t *pFreq, //get the valid freq after scan
142                 uint16_t *pScanTBL,
143                 uint16_t *ScanTBLsize,
144                 uint16_t scandir,
145                 uint16_t space);
146
147
148 static int RDAFM_read(uint8_t chipAddr, uint8_t addr, uint16_t *val);
149 static int RDAFM_write(uint8_t chipAddr, uint8_t addr, uint16_t val);
150 static int fm_setup_cdev(struct fm *fm);
151 static int fm_ops_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
152 static loff_t fm_ops_lseek(struct file *filp, loff_t off, int whence);
153 static int fm_ops_open(struct inode *inode, struct file *filp);
154 static int fm_ops_release(struct inode *inode, struct file *filp);
155
156 static int fm_init(void);
157 static int fm_destroy(struct fm *fm);
158 static int fm_powerup(struct fm *fm, struct fm_tune_parm *parm);
159 static int fm_powerdown(struct fm *fm);
160
161 static int fm_tune(struct fm *fm, struct fm_tune_parm *parm);
162 static int fm_seek(struct fm *fm, struct fm_seek_parm *parm);
163 static int fm_scan(struct fm *fm, struct fm_scan_parm *parm);
164 static int fm_setvol(struct fm *fm, uint32_t vol);
165 static int fm_getvol(struct fm *fm, uint32_t *vol);
166 static int fm_getrssi(struct fm *fm, uint32_t *rssi);
167 static int fm_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data);
168
169
170
171
172
173
174 static uint16_t RDAFM_CHIP_ID = 0x5808;
175 static RDA_RADIO_WORK_E RDA_RADIO_WorkType = FM_RECEIVER;
176
177
178
179 #if 1
180 static uint16_t RDA5802N_initialization_reg[]={
181         0xC005, //02h 
182         0x0000,
183         0x0400,
184         0xC6ED, //0x86AD, //05h
185         0x6000,
186         0x721A, //0x42C6
187         0x0000,
188         0x0000,
189         0x0000,  //0x0ah
190         0x0000,
191         0x0000,
192         0x0000,
193         0x0000,
194         0x0000,
195         0x0000,  //0x10h
196         0x0019,
197         0x2A11,
198         0xB042,  
199         0x2A11,  
200         0xB831,  //0x15h 
201         0xC000,
202         0x2A91,
203         0x9400,
204         0x00A8,
205         0xc400,  //0x1ah
206         0xF7CF,  //Ìá¸ßÔ¶¶ËÔëÉùÒÖÖÆ  
207         0x2414, //0x2ADC,  //0x1ch ÌáÉýVIO VDDÖ®¼äѹ²îÒýÆðµÄ²»Á¼
208         0x806F, 
209         0x4608,
210         0x0086,
211         0x0661, //0x20H
212         0x0000,
213         0x109E,
214         0x23C8,
215         0x0406,
216         0x0E1C, //0x25H
217 };
218 #else
219 static uint16_t RDA5802N_initialization_reg[]={
220         0xc401, //02h
221         0x0000,
222         0x0400,
223         0x86ad, //05h//
224         0x0000,
225         0x42c6,
226         0x0000,
227         0x0000,
228         0x0000,  //0x0ah
229         0x0000,
230         0x0000,
231         0x0000,
232         0x0000,
233         0x0000,
234         0x0000,  //0x10h
235         0x0019,  
236         0x2a11,
237         0xa053,//0x80,0x53,
238         0x3e11,//0x22,0x11,     
239         0xfc7d,  //0x15h 
240         0xc000,
241         0x2a91,
242         0x9400,
243         0x00a8,
244         0xc400,  //0x1ah
245         0xe000,
246         0x2b1d, //0x23,0x14
247         0x816a,
248         0x4608,
249         0x0086,
250         0x0661,  //0x20h
251         0x0000,  
252         0x109e,
253         0x2244,
254         0x0408,  //0x24
255         0x0408,  //0x25
256 };
257 #endif
258
259 static RDA_FM_REG_T RDA5820NS_TX_initialization_reg[]={
260         {0x02, 0xE003},
261         {0xFF, 100},    // if address is 0xFF, sleep value ms
262         {0x02, 0xE001},
263         {0x19, 0x88A8},
264         {0x1A, 0x4290},
265         {0x68, 0x0AF0},
266         {0x40, 0x0001},
267         {0x41, 0x41FF},
268         {0xFF, 500},
269         {0x03, 0x1B90},
270 };
271
272 static RDA_FM_REG_T RDA5820NS_RX_initialization_reg[]={
273         {0x02, 0x0002}, //Soft reset
274         {0xFF, 100},    // wait
275         {0x02, 0xC001},  //Power Up 
276         {0x05, 0x888F},  //LNAP  0x884F --LNAN
277         {0x06, 0x6000},
278         {0x13, 0x80E1},
279         {0x14, 0x2A11},
280         {0x1C, 0x22DE},
281         {0x21, 0x0020},
282         {0x03, 0x1B90},
283 };
284
285
286
287 static struct file_operations fm_ops = {
288         .owner = THIS_MODULE,
289         .unlocked_ioctl = fm_ops_ioctl,
290         .llseek = fm_ops_lseek,
291         .open = fm_ops_open,
292         .release = fm_ops_release,
293 };
294
295 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
296 static DECLARE_MUTEX(fm_ops_mutex);
297 #else
298 DEFINE_SEMAPHORE(fm_ops_mutex);
299 #endif
300
301 static int RDAFM_GetChipID(uint8_t chipAddr, uint16_t *pChipID)
302 {
303         int err;
304         int ret = -1;
305         uint16_t val = 0x0002;
306
307         //Reset RDA FM
308         err = RDAFM_write(chipAddr, 0x02, val);
309         if(err < 0){
310 #ifdef FMDEBUG
311                 FM_DEBUG("RDAFM_GetChipID: reset FM chip failed!\n");
312 #endif
313                 ret = -1;
314                 return ret;
315         }
316         msleep(80);
317
318         val = 0;
319         err = RDAFM_read(chipAddr, 0x0C, &val);
320         if (err == 0)
321         {
322                 if ((0x5802 == val) || (0x5803 == val))
323                 {
324                         err = RDAFM_read(chipAddr, 0x0E, &val);
325
326                         if (err == 0)
327                                 *pChipID = val;
328                         else
329                                 *pChipID = 0x5802;
330
331 #ifdef FMDEBUG
332                         FM_DEBUG("RDAFM_GetChipID: Chip ID = %04X\n", val);
333 #endif
334
335                         ret = 0;
336
337                 }
338                 else if ((0x5805 == val) || (0x5820 == val))
339                 {
340                         *pChipID = val;
341                         ret = 0;
342                 }
343                 else
344                 {
345 #ifdef FMDEBUG
346                         FM_DEBUG("RDAFM_GetChipID: get chip ID failed! get value = %04X\n", val);
347 #endif
348                         ret = -1;
349                 }
350
351         }
352         else
353         {
354 #ifdef FMDEBUG
355                 FM_DEBUG("RDAFM_GetChipID: get chip ID failed!\n");
356 #endif
357                 ret = -1;
358         }
359
360         return ret;
361 }
362
363
364 /*
365  *  RDAFM_read
366  */
367 static int RDAFM_read(uint8_t chipAddr, uint8_t regAddr, uint16_t *val)
368 {
369         int ret = -1;
370         ret = rda_gpio_i2c_read_1_addr_2_data(chipAddr, regAddr, val);
371
372         return ret;
373 }
374
375 /*
376  *  RDAFM_write
377  */
378 static int RDAFM_write(uint8_t chipAddr, uint8_t regAddr, uint16_t val)
379 {
380         int n;
381
382         n = rda_gpio_i2c_write_1_addr_2_data(chipAddr, regAddr, val);
383         if (n < 0)
384         {
385                 FM_ALERT("RDAFM_write send:0x%X err:%d\n", regAddr, n);
386                 return -1;
387         }
388
389         return 0;
390 }
391
392
393 static int RDAFM_clear_hmute(uint8_t chipAddr)
394 {
395         int ret = 0;
396         uint16_t tRegValue = 0;
397
398         FM_DEBUG("RDAFM_clear_hmute\n");
399
400         ret = RDAFM_read(chipAddr, 0x02, &tRegValue);
401         if (ret < 0)
402         {
403                 FM_ALERT("RDAFM_clear_hmute  read register failed!\n"); 
404                 return -1;
405         }
406
407         tRegValue |= (1 << 14);
408
409         ret = RDAFM_write(chipAddr, 0x02, tRegValue);
410
411         if (ret < 0)
412         {
413                 FM_ALERT("RDAFM_clear_hmute  write register failed!\n"); 
414                 return -1;
415         }
416
417         if(fm_tune_data.byPowerUp){
418                 if (fm_tune(g_fm_struct, &(fm_tune_data.parm)) < 0)
419                 {
420                         fm_tune_data.byPowerUp = false;
421                         memset(&fm_tune_data.parm, 0, sizeof(fm_tune_data.parm));
422                         return -EPERM;
423                 }
424                 fm_tune_data.byPowerUp = false;
425                 memset(&fm_tune_data.parm, 0, sizeof(fm_tune_data.parm));
426         }
427
428         return 0;
429 }
430
431
432
433 static int RDAFM_enable_hmute(uint8_t chipAddr)
434 {
435         int ret = 0;
436         uint16_t tRegValue = 0;
437
438         FM_DEBUG("RDAFM_enable_hmute\n");
439
440         ret = RDAFM_read(chipAddr, 0x02, &tRegValue);
441         if (ret < 0)
442         {
443                 FM_ALERT("RDAFM_enable_hmute  read register failed!\n"); 
444                 return -1;
445         }
446
447         tRegValue &= (~(1 << 14));
448
449         ret = RDAFM_write(chipAddr, 0x02, tRegValue);
450
451         if (ret < 0)
452         {
453                 FM_ALERT("RDAFM_enable_hmute  write register failed!\n"); 
454                 return -1;
455         }
456
457         return 0;
458 }
459
460
461 static bool RDAFM_Scan(uint8_t chipAddr, 
462                 uint16_t min_freq, uint16_t max_freq,
463                 uint16_t *pFreq,
464                 uint16_t *pScanTBL, 
465                 uint16_t *ScanTBLsize, 
466                 uint16_t scandir, 
467                 uint16_t space)
468 {
469         uint16_t tFreq, tRegValue = 0;
470         uint16_t tmp_scanTBLsize = *ScanTBLsize;
471         int ret = -1;
472         bool isTrueStation = false;
473         uint16_t oldValue = 0;
474         int channel = 0;
475
476         if((!pScanTBL) || (tmp_scanTBLsize == 0)) {
477                 return false;
478         }
479
480         //clear the old value of pScanTBL
481         memset(pScanTBL, 0, sizeof(uint16_t)*RDA599X_SCANTBL_SIZE);
482
483         if(tmp_scanTBLsize > RDA599X_SCANTBL_SIZE)
484         {
485                 tmp_scanTBLsize = RDA599X_SCANTBL_SIZE;
486         }
487
488         //scan up
489         if(scandir == RDA599X_FM_SCAN_UP){ // now, only support scan up
490                 tFreq = min_freq;
491         }else{ //scan down
492                 tFreq = max_freq;//max_freq compare need or not   
493         }
494
495         //mute FM
496         RDAFM_enable_hmute(chipAddr);
497
498         //set seekth
499         tRegValue = 0;
500         RDAFM_read(chipAddr, 0x05, &tRegValue);
501         tRegValue &= (~(0x7f<<8));
502         tRegValue |= ((0x8 & 0x7f) << 8);
503         RDAFM_write(chipAddr, 0x05, tRegValue);
504         msleep(50);
505
506         atomic_set(&scan_complete_flag, 1);
507
508         do {
509                 if(atomic_read(&scan_complete_flag) == 0)
510                         break;
511                 isTrueStation = false;
512
513                 //set channel and enable TUNE
514                 tRegValue = 0;
515                 RDAFM_read(chipAddr, 0x03, &tRegValue);
516                 tRegValue &= (~(0x03ff<<6)); //clear bit[15:6]
517                 channel = tFreq - min_freq; 
518                 tRegValue |= ((channel << 6) | (1 << 4)); //set bit[15:6] and bit[4]
519                 ret = RDAFM_write(chipAddr, 0x03, tRegValue);
520                 msleep(40);
521
522                 //read 0x0B and check FM_TRUE(bit[8])
523                 tRegValue = 0;
524                 ret = RDAFM_read(chipAddr, 0x0B, &tRegValue);
525                 if(!ret){
526                         if((tRegValue & 0x0100) == 0x0100){
527                                 isTrueStation = true;
528                         }
529                 }
530
531                 //if this freq is a true station, read the channel
532                 if(isTrueStation){
533                         //tRegValue = 0;
534                         //RDAFM_read(chipAddr, 0x0A, &tRegValue);
535                         //channel = ((tRegValue) & 0x03ff) - 5;
536                         channel = channel - 5;
537                         if((channel >= 0) && (channel != 85)){
538                                 oldValue = *(pScanTBL+(channel/16));
539                                 oldValue |= (1<<(channel%16));
540                                 *(pScanTBL+(channel/16)) = oldValue;
541                         }
542                 }
543
544                 //increase freq
545                 tFreq += space;
546         }while( tFreq <= max_freq );
547
548 #if defined(MTK_MT6515) && defined(MT6626)
549         *(pScanTBL+13) = 0xb2d4;
550         *(pScanTBL+14) = 0xb2d4;
551         *(pScanTBL+15) = 0xb2d4;
552 #endif
553
554         *ScanTBLsize = tmp_scanTBLsize;
555         *pFreq = 0;
556
557         //clear FM mute
558         RDAFM_clear_hmute(chipAddr);
559
560         return true;
561 }
562
563
564 static int fm_setup_cdev(struct fm *fm)
565 {
566         int err;
567
568         err = alloc_chrdev_region(&fm->dev_t, 0, 1, FM_NAME);
569         if (err) {
570                 FM_ALERT("alloc dev_t failed\n");
571                 return -1;
572         }
573
574         FM_ALERT("alloc %s:%d:%d\n", FM_NAME,
575                         MAJOR(fm->dev_t), MINOR(fm->dev_t));
576
577         cdev_init(&fm->cdev, &fm_ops);
578
579         fm->cdev.owner = THIS_MODULE;
580         fm->cdev.ops = &fm_ops;
581
582         err = cdev_add(&fm->cdev, fm->dev_t, 1);
583         if (err) {
584                 FM_ALERT("alloc dev_t failed\n");
585                 return -1;
586         }
587
588         fm->cls = class_create(THIS_MODULE, FM_NAME);
589         if (IS_ERR(fm->cls)) {
590                 err = PTR_ERR(fm->cls);
591                 FM_ALERT("class_create err:%d\n", err);
592                 return err;            
593         }    
594         fm->dev = device_create(fm->cls, NULL, fm->dev_t, NULL, FM_NAME);
595
596         return 0;
597 }
598
599
600
601 static int fm_ops_ioctl(struct file *filp,
602                 unsigned int cmd, unsigned long arg)
603 {
604         int ret = 0;
605         struct fm *fm = container_of(filp->f_dentry->d_inode->i_cdev, struct fm, cdev);
606
607         FM_DEBUG("%s cmd(%x)\n", __func__, cmd);
608
609         switch(cmd)
610         {
611                 case FM_IOCTL_POWERUP:
612                         {
613                                 struct fm_tune_parm parm;
614                                 FM_DEBUG("FM_IOCTL_POWERUP\n");
615
616                                 if (copy_from_user(&parm, (void*)arg, sizeof(struct fm_tune_parm)))
617                                         return -EFAULT;
618
619                                 if (down_interruptible(&fm_ops_mutex))
620                                         return -EFAULT;
621                                 ret = fm_powerup(fm, &parm);
622                                 up(&fm_ops_mutex);
623                                 if (copy_to_user((void*)arg, &parm, sizeof(struct fm_tune_parm)))
624                                         return -EFAULT;
625                                 break;
626                         }
627
628                 case FM_IOCTL_POWERDOWN:
629                         {
630                                 FM_DEBUG("FM_IOCTL_POWERDOWN\n");
631                                 if (down_interruptible(&fm_ops_mutex))
632                                         return -EFAULT;
633                                 ret = fm_powerdown(fm);
634                                 up(&fm_ops_mutex);
635                                 break;
636                         }
637
638                         // tune (frequency, auto Hi/Lo ON/OFF )
639                 case FM_IOCTL_TUNE:
640                         {
641                                 struct fm_tune_parm parm;
642                                 FM_DEBUG("FM_IOCTL_TUNE\n");
643
644                                 if (copy_from_user(&parm, (void*)arg, sizeof(struct fm_tune_parm)))
645                                         return -EFAULT;
646
647                                 if (down_interruptible(&fm_ops_mutex))
648                                         return -EFAULT;
649                                 ret = fm_tune(fm, &parm);
650                                 up(&fm_ops_mutex);
651
652                                 if (copy_to_user((void*)arg, &parm, sizeof(struct fm_tune_parm)))
653                                         return -EFAULT;
654
655                                 break;
656                         }
657
658                 case FM_IOCTL_SEEK:
659                         {
660                                 struct fm_seek_parm parm;
661                                 FM_DEBUG("FM_IOCTL_SEEK\n");
662
663                                 if (copy_from_user(&parm, (void*)arg, sizeof(struct fm_seek_parm)))
664                                         return -EFAULT;
665
666                                 if (down_interruptible(&fm_ops_mutex))
667                                         return -EFAULT;
668                                 ret = fm_seek(fm, &parm);
669                                 up(&fm_ops_mutex);
670
671                                 if (copy_to_user((void*)arg, &parm, sizeof(struct fm_seek_parm)))
672                                         return -EFAULT;
673
674                                 break;
675                         }
676
677                 case FM_IOCTL_SETVOL:
678                         {
679                                 uint32_t vol;
680                                 FM_DEBUG("FM_IOCTL_SETVOL\n");
681
682                                 if(copy_from_user(&vol, (void*)arg, sizeof(uint32_t))) {
683                                         FM_ALERT("copy_from_user failed\n");
684                                         return -EFAULT;
685                                 }
686
687                                 if (down_interruptible(&fm_ops_mutex))
688                                         return -EFAULT;
689                                 ret = fm_setvol(fm, vol);
690                                 up(&fm_ops_mutex);
691
692                                 break;
693                         }
694
695                 case FM_IOCTL_GETVOL:
696                         {
697                                 uint32_t vol;
698                                 FM_DEBUG("FM_IOCTL_GETVOL\n");
699
700                                 if (down_interruptible(&fm_ops_mutex))
701                                         return -EFAULT;
702                                 ret = fm_getvol(fm, &vol);
703                                 up(&fm_ops_mutex);
704
705                                 if (copy_to_user((void*)arg, &vol, sizeof(uint32_t)))
706                                         return -EFAULT;
707
708                                 break;
709                         }
710
711                 case FM_IOCTL_MUTE:
712                         {
713                                 uint32_t bmute;
714                                 FM_DEBUG("FM_IOCTL_MUTE\n");
715
716                                 if (copy_from_user(&bmute, (void*)arg, sizeof(uint32_t)))
717                                 {
718                                         FM_DEBUG("copy_from_user mute failed!\n");
719                                         return -EFAULT;    
720                                 }
721
722                                 FM_DEBUG("FM_IOCTL_MUTE:%d\n", bmute); 
723                                 if (down_interruptible(&fm_ops_mutex))
724                                         return -EFAULT;
725
726                                 if (bmute){
727                                         ret = RDAFM_enable_hmute(fm->chipAddr);
728                                 }else{
729                                         ret = RDAFM_clear_hmute(fm->chipAddr);
730                                 }
731
732                                 up(&fm_ops_mutex);
733
734                                 break;
735                         }
736
737                 case FM_IOCTL_GETRSSI:
738                         {
739                                 uint32_t rssi;
740                                 FM_DEBUG("FM_IOCTL_GETRSSI\n");
741
742                                 if (down_interruptible(&fm_ops_mutex))
743                                         return -EFAULT;
744
745                                 ret = fm_getrssi(fm, &rssi);
746                                 up(&fm_ops_mutex);
747
748                                 if (copy_to_user((void*)arg, &rssi, sizeof(uint32_t)))
749                                         return -EFAULT;
750
751                                 break;
752                         }
753
754                 case FM_IOCTL_RW_REG:
755                         {
756                                 struct fm_ctl_parm parm_ctl;
757                                 FM_DEBUG("FM_IOCTL_RW_REG\n");
758
759                                 if (copy_from_user(&parm_ctl, (void*)arg, sizeof(struct fm_ctl_parm)))
760                                         return -EFAULT;
761
762                                 if (down_interruptible(&fm_ops_mutex))
763                                         return -EFAULT;
764
765                                 if(parm_ctl.rw_flag == 0) //write
766                                 {
767                                         ret = RDAFM_write(fm->chipAddr, parm_ctl.addr, parm_ctl.val);
768                                 }
769                                 else
770                                 {
771                                         ret = RDAFM_read(fm->chipAddr, parm_ctl.addr, &parm_ctl.val);
772                                 }
773
774                                 up(&fm_ops_mutex);
775                                 if ((parm_ctl.rw_flag == 0x01) && (!ret)) // Read success.
776                                 { 
777                                         if (copy_to_user((void*)arg, &parm_ctl, sizeof(struct fm_ctl_parm)))
778                                                 return -EFAULT;
779                                 }
780                                 break;
781                         }
782
783                 case FM_IOCTL_GETCHIPID:
784                         {
785                                 uint16_t chipid;            
786
787                                 if (down_interruptible(&fm_ops_mutex))
788                                         return -EFAULT;
789
790                                 RDAFM_GetChipID(fm->chipAddr, &chipid);
791                                 //chipid = fm->chip_id;
792                                 chipid = 0x6620;
793                                 FM_DEBUG("FM_IOCTL_GETCHIPID:%04x\n", chipid);   
794                                 up(&fm_ops_mutex);
795
796                                 if (copy_to_user((void*)arg, &chipid, sizeof(uint16_t)))
797                                         return -EFAULT;
798
799                                 break;
800                         }
801
802                 case FM_IOCTL_IS_FM_POWERED_UP:
803                         {
804                                 uint32_t powerup;
805                                 FM_DEBUG("FM_IOCTL_IS_FM_POWERED_UP");
806                                 if (fm->powerup) {
807                                         powerup = 1;
808                                 } else {
809                                         powerup = 0;
810                                 }
811                                 if (copy_to_user((void*)arg, &powerup, sizeof(uint32_t)))
812                                         return -EFAULT;
813                                 break;
814                         }
815
816 #ifdef FMDEBUG
817                 case FM_IOCTL_DUMP_REG:
818                         {
819                                 uint16_t chipid = 0;
820                                 if (down_interruptible(&fm_ops_mutex))
821                                         return -EFAULT;
822                                 RDAFM_GetChipID(fm->chipAddr, &chipid);
823                                 up(&fm_ops_mutex);
824
825                                 break;
826                         }
827 #endif
828
829                 case FM_IOCTL_SCAN:
830                         {
831                                 struct fm_scan_parm parm;
832                                 FM_DEBUG("FM_IOCTL_SCAN\n");
833                                 if (false == fm->powerup){
834                                         return -EFAULT;
835                                 }
836                                 if(copy_from_user(&parm, (void*)arg, sizeof(struct fm_scan_parm))){
837                                         return -EFAULT;
838                                 }
839                                 if (down_interruptible(&fm_ops_mutex)){
840                                         return -EFAULT;
841                                 }
842                                 fm_scan(fm, &parm);
843                                 up(&fm_ops_mutex);
844
845                                 if(copy_to_user((void*)arg, &parm, sizeof(struct fm_scan_parm))){
846                                         return -EFAULT;
847                                 }
848
849                                 break;
850                         }
851
852                 case FM_IOCTL_STOP_SCAN:
853                         {
854                                 FM_DEBUG("FM_IOCTL_STOP_SCAN\n");
855                                 break;
856                         }
857
858                 case FM_IOCTL_SCAN_GETRSSI:
859                         {
860                                 FM_DEBUG("FM_IOCTL_SCAN_GETRSSI\n");
861                                 break;
862                         }
863
864                 case FM_IOCTL_GETMONOSTERO:
865                         {
866                                 FM_DEBUG("FM_IOCTL_GETMONOSTERO\n");
867                                 break;
868                         }
869
870                 case FM_IOCTL_SETMONOSTERO:
871                         {
872                                 FM_DEBUG("FM_IOCTL_SETMONOSTERO\n");
873                                 break;
874                         }
875
876                 case FM_IOCTL_GETCURPAMD:
877                         {
878                                 FM_DEBUG("FM_IOCTL_GETCURPAMD\n");
879                                 break;
880                         }
881
882                 case FM_IOCTL_EM_TEST:
883                         {
884                                 FM_DEBUG("FM_IOCTL_EM_TEST\n");
885                                 break;
886                         }
887
888                 case FM_IOCTL_RDS_SUPPORT:
889                         {
890                                 FM_DEBUG("FM_IOCTL_RDS_SUPPORT\n");
891                                 break;
892                         }
893
894                 case FM_IOCTL_RDS_ONOFF:
895                         {
896                                 FM_DEBUG("FM_IOCTL_RDS_ONOFF\n");
897                                 break;
898                         }
899
900                 case FM_IOCTL_GETGOODBCNT:
901                         {
902                                 FM_DEBUG("FM_IOCTL_GETGOODBCNT\n");
903                                 break;
904                         }
905
906                 case FM_IOCTL_GETBADBNT:
907                         {
908                                 FM_DEBUG("FM_IOCTL_GETBADBNT\n");
909                                 break;
910                         }
911
912                 case FM_IOCTL_GETBLERRATIO:
913                         {
914                                 FM_DEBUG("FM_IOCTL_GETBLERRATIO\n");
915                                 break;
916                         }
917
918                 case FM_IOCTL_POWERUP_TX:
919                         {
920                                 FM_DEBUG("FM_IOCTL_POWERUP_TX\n");
921                                 break;
922                         }
923
924                 case FM_IOCTL_TUNE_TX:
925                         {
926                                 FM_DEBUG("FM_IOCTL_TUNE_TX\n");
927                                 break;
928                         }
929
930                 case FM_IOCTL_TX_SUPPORT:
931                         {
932                                 FM_DEBUG("FM_IOCTL_TX_SUPPORT\n");
933                                 break;
934                         }
935
936                 case FM_IOCTL_RDSTX_ENABLE:
937                         {
938                                 FM_DEBUG("FM_IOCTL_RDSTX_ENABLE\n");
939                                 break;
940                         }
941
942                 case FM_IOCTL_RDSTX_SUPPORT:
943                         {
944                                 FM_DEBUG("FM_IOCTL_RDSTX_SUPPORT\n");
945                                 break;
946                         }
947
948                 case FM_IOCTL_TX_SCAN:
949                         {
950                                 FM_DEBUG("FM_IOCTL_TX_SCAN\n");
951                                 break;
952                         }
953
954                 case FM_IOCTL_RDS_TX:
955                         {
956                                 FM_DEBUG("FM_IOCTL_RDS_TX\n");
957                                 break;
958                         }
959
960                 case FM_IOCTL_OVER_BT_ENABLE:
961                         {
962                                 FM_DEBUG("FM_IOCTL_OVER_BT_ENABLE\n");
963                                 break;
964                         }
965
966                 case FM_IOCTL_ANA_SWITCH:
967                         {
968                                 FM_DEBUG("FM_IOCTL_ANA_SWITCH\n");
969                                 break;
970                         }
971
972                 case FM_IOCTL_GETCAPARRAY:
973                         {
974                                 FM_DEBUG("FM_IOCTL_GETCAPARRAY\n");
975                                 break;
976                         }
977
978                 case FM_IOCTL_GPS_RTC_DRIFT:
979                         {
980                                 FM_DEBUG("FM_IOCTL_GPS_RTC_DRIFT\n");
981                                 break;
982                         }
983
984                 case FM_IOCTL_I2S_SETTING:
985                         {
986                                 FM_DEBUG("FM_IOCTL_I2S_SETTING\n");
987                                 break;
988                         }
989
990                 case FM_IOCTL_RDS_GROUPCNT:
991                         {
992                                 FM_DEBUG("FM_IOCTL_RDS_GROUPCNT\n");
993                                 break;
994                         }
995
996                 case FM_IOCTL_RDS_GET_LOG:
997                         {
998                                 FM_DEBUG("FM_IOCTL_RDS_GET_LOG\n");
999                                 break;
1000                         }
1001
1002                 case FM_IOCTL_GET_HW_INFO:
1003                         {
1004                                 FM_DEBUG("FM_IOCTL_GET_HW_INFO\n");
1005                                 break;
1006                         }
1007                 default:
1008                         {
1009                                 FM_DEBUG("default\n");
1010                                 break;
1011                         }
1012         }
1013
1014         return ret;
1015 }
1016 static loff_t fm_ops_lseek(struct file *filp, loff_t off, int whence)
1017 {
1018 //      struct fm *fm = filp->private_data;
1019
1020         if(whence == SEEK_END){
1021                 //fm_hwscan_stop(fm);
1022                 atomic_set(&scan_complete_flag, 0);
1023         }else if(whence == SEEK_SET){  
1024                 //FM_EVENT_SEND(fm->rds_event, FM_RDS_DATA_READY);
1025         }   
1026         return off;    
1027 }
1028
1029 static int fm_ops_open(struct inode *inode, struct file *filp)
1030 {
1031         struct fm *fm = container_of(inode->i_cdev, struct fm, cdev);
1032
1033         FM_DEBUG("%s\n", __func__);
1034
1035         if (down_interruptible(&fm_ops_mutex))
1036                 return -EFAULT;
1037
1038         // TODO: only have to set in the first time?
1039         // YES!!!!
1040
1041         fm->ref++;
1042
1043         up(&fm_ops_mutex);
1044
1045         filp->private_data = fm;
1046
1047         // TODO: check open flags
1048
1049         return 0;
1050 }
1051
1052 static int fm_ops_release(struct inode *inode, struct file *filp)
1053 {
1054         int err = 0;
1055         struct fm *fm = container_of(inode->i_cdev, struct fm, cdev);
1056
1057         FM_DEBUG("%s\n", __func__);
1058
1059         if (down_interruptible(&fm_ops_mutex))
1060                 return -EFAULT;
1061         fm->ref--;
1062         if(fm->ref < 1) {
1063                 if(fm->powerup == true) {
1064                         fm_powerdown(fm);           
1065                 }
1066         }
1067
1068         up(&fm_ops_mutex);
1069
1070         return err;
1071 }
1072
1073 static int fm_init(void)
1074 {
1075         int err;
1076         struct fm *fm = NULL;
1077         int ret = -1;
1078
1079
1080         FM_DEBUG("%s()\n", __func__);
1081         if (!(fm = kzalloc(sizeof(struct fm), GFP_KERNEL)))
1082         {
1083                 FM_ALERT("-ENOMEM\n");
1084                 err = -ENOMEM;
1085                 goto ERR_EXIT;
1086         }
1087
1088         fm->ref = 0;
1089         fm->powerup = false;
1090         fm->chipAddr = RDAFM_SLAVE_ADDR;
1091         atomic_set(&scan_complete_flag, 0);
1092
1093         // First, read 5802NM chip ID
1094         FM_DEBUG("%s()First, read 5802NM chip ID\n", __func__);
1095         ret = RDAFM_GetChipID(fm->chipAddr, &RDAFM_CHIP_ID);
1096         FM_DEBUG("%s() 5802NM chip ID = 0x%04x\n", __func__, RDAFM_CHIP_ID);
1097         // if failed, means use FM in 5990P_E
1098         if(ret < 0){
1099                 // enable the FM chip in combo
1100                 FM_DEBUG("%s() enable the FM chip in combo\n", __func__);
1101                 ret = rda_fm_power_on();
1102                 if(ret < 0){
1103                         err = -ENOMEM;
1104                         goto ERR_EXIT;
1105                 }
1106                 msleep(100);
1107                 ret = RDAFM_GetChipID(fm->chipAddr, &RDAFM_CHIP_ID);
1108                 FM_DEBUG("%s() the FM in combo chip ID = 0x%04x\n", __func__, RDAFM_CHIP_ID);
1109                 if(ret < 0){
1110                         err = -ENOMEM;
1111                         goto ERR_EXIT;
1112                 }else{
1113                         fm->chip_id = RDAFM_CHIP_ID;
1114                 }
1115
1116                 // disable the FM chip for power saving
1117                 ret = rda_fm_power_off();
1118                 if(ret < 0){
1119                         err = -ENOMEM;
1120                         goto ERR_EXIT;
1121                 }
1122         }else{
1123                 fm->chip_id = RDAFM_CHIP_ID;
1124         }
1125
1126
1127
1128         if ((err = fm_setup_cdev(fm)))
1129         {
1130                 goto ERR_EXIT;
1131         }
1132
1133         g_fm_struct = fm;
1134
1135         /***********Add porc file system*************/
1136
1137         g_fm_proc = create_proc_entry(FM_PROC_FILE, 0444, NULL);
1138         if (g_fm_proc == NULL) {
1139                 FM_ALERT("create_proc_entry failed\n");
1140                 err = -ENOMEM;
1141                 goto ERR_EXIT;
1142         } else {
1143                 g_fm_proc->read_proc = fm_proc_read;
1144                 g_fm_proc->write_proc = NULL;
1145                 //g_fm_proc->owner = THIS_MODULE;
1146                 FM_ALERT("create_proc_entry success\n");
1147         }
1148
1149         /********************************************/
1150
1151         FM_DEBUG("fm_init is ok!\n");
1152
1153         return 0;
1154
1155 ERR_EXIT:
1156         kfree(fm);
1157
1158         return err;
1159 }
1160
1161 static int fm_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data)
1162 {
1163         int cnt= 0;
1164         struct fm *fm  = g_fm_struct;
1165         FM_ALERT("Enter fm_proc_read.\n");
1166         if(off != 0)
1167                 return 0;
1168         if (fm != NULL && fm->powerup) {
1169                 cnt = sprintf(page, "1\n");
1170         } else {
1171                 cnt = sprintf(page, "0\n");
1172         }
1173         *eof = 1;
1174         FM_ALERT("Leave fm_proc_read. cnt = %d\n", cnt);
1175         return cnt;
1176 }
1177
1178
1179 static int fm_destroy(struct fm *fm)
1180 {
1181         int err = 0;
1182
1183         FM_DEBUG("%s\n", __func__);
1184
1185         device_destroy(fm->cls, fm->dev_t);
1186         class_destroy(fm->cls);
1187
1188         cdev_del(&fm->cdev);
1189         unregister_chrdev_region(fm->dev_t, 1);
1190
1191         fm_powerdown(fm);
1192
1193         /***********************************/
1194         remove_proc_entry(FM_PROC_FILE, NULL);
1195
1196         /**********************************/
1197
1198         // FIXME: any other hardware configuration ?
1199
1200         // free all memory
1201         kfree(fm);
1202
1203         return err;
1204 }
1205
1206 /*
1207  *  fm_powerup
1208  */
1209 static int fm_powerup(struct fm *fm, struct fm_tune_parm *parm)
1210 {
1211         int i;
1212         uint16_t tRegValue = 0x0002;
1213         int ret = -1;
1214
1215
1216         if (fm->powerup)
1217         {
1218                 parm->err = FM_BADSTATUS;
1219                 return -EPERM;
1220         }
1221
1222         //  if chip_id is ID_RDA5820NS, enable the FM chip in combo
1223         if(fm->chip_id == ID_RDA5820NS){
1224                 ret = rda_fm_power_on();
1225                 if(ret < 0){
1226                         return -EPERM;
1227                 }
1228                 msleep(100);
1229         }
1230
1231
1232         //Reset RDA FM
1233         tRegValue = 0x0002;
1234         RDAFM_write(fm->chipAddr, 0x02, tRegValue);
1235         msleep(100);
1236
1237
1238
1239         if (ID_RDA5802N == RDAFM_CHIP_ID){
1240                 for (i=0; i<((sizeof(RDA5802N_initialization_reg)) / (sizeof(uint16_t))); i++)
1241                 {
1242                         ret = RDAFM_write(fm->chipAddr, i+2, RDA5802N_initialization_reg[i]);
1243
1244                         if (ret < 0)
1245                         {
1246                                 FM_DEBUG("fm_powerup init failed!\n");
1247
1248                                 parm->err = FM_FAILED;
1249
1250                                 return -EPERM;
1251                         }
1252                 }
1253
1254         }else if (ID_RDA5820NS == RDAFM_CHIP_ID){
1255                 if(RDA_RADIO_WorkType == FM_RECEIVER){
1256                         for (i = 0; i < ((sizeof(RDA5820NS_RX_initialization_reg)) / (sizeof(RDA_FM_REG_T))); i++)
1257                         {
1258                                 if(RDA5820NS_RX_initialization_reg[i].address == 0xFF){
1259                                         msleep(RDA5820NS_RX_initialization_reg[i].value);
1260                                 }else{
1261                                         ret = RDAFM_write(fm->chipAddr, RDA5820NS_RX_initialization_reg[i].address, RDA5820NS_RX_initialization_reg[i].value);
1262                                         if (ret < 0)
1263                                         {
1264                                                 FM_DEBUG("fm_powerup init failed!\n");
1265                                                 parm->err = FM_FAILED;
1266                                                 return -EPERM;
1267                                         }
1268                                 }
1269                         }
1270                 }else{
1271                         for (i = 0; i < ((sizeof(RDA5820NS_TX_initialization_reg)) / (sizeof(RDA_FM_REG_T))); i++)
1272                         {
1273                                 if(RDA5820NS_TX_initialization_reg[i].address == 0xFF){
1274                                         msleep(RDA5820NS_TX_initialization_reg[i].value);
1275                                 }else{
1276                                         ret = RDAFM_write(fm->chipAddr, RDA5820NS_TX_initialization_reg[i].address, RDA5820NS_TX_initialization_reg[i].value);
1277                                         if (ret < 0)
1278                                         {
1279                                                 FM_DEBUG("fm_powerup init failed!\n");
1280                                                 parm->err = FM_FAILED;
1281                                                 return -EPERM;
1282                                         }
1283                                 }
1284                         }
1285                 }
1286
1287         }
1288
1289
1290         FM_DEBUG("pwron ok\n");
1291         fm->powerup = true;
1292
1293         if (fm_tune(fm, parm) < 0)
1294         {
1295                 return -EPERM;
1296         }
1297         fm_tune_data.byPowerUp = true;
1298         memcpy(&fm_tune_data.parm, parm, sizeof(fm_tune_data.parm));
1299
1300         parm->err = FM_SUCCESS;
1301
1302         return 0;
1303
1304 }
1305
1306 /*
1307  *  fm_powerdown
1308  */
1309 static int fm_powerdown(struct fm *fm)
1310 {
1311         uint16_t tRegValue = 0;
1312         int ret = -1;
1313
1314         RDAFM_read(fm->chipAddr, 0x02, &tRegValue);
1315         tRegValue &= (~(1 << 0));
1316         RDAFM_write(fm->chipAddr, 0x02, tRegValue);
1317
1318         if(fm->chip_id == ID_RDA5820NS){
1319                 ret = rda_fm_power_off();
1320                 if(ret < 0){
1321                         return -EPERM;
1322                 }
1323         }
1324
1325         fm->powerup = false;
1326         FM_ALERT("pwrdown ok\n");
1327
1328         return 0;
1329 }
1330
1331 /*
1332  *  fm_seek
1333  */
1334 static int fm_seek(struct fm *fm, struct fm_seek_parm *parm)
1335 {
1336         int ret = 0;
1337         uint16_t val = 0;
1338         uint8_t spaec = 1;
1339         uint16_t tFreq = 875;
1340         uint16_t tRegValue = 0;
1341         uint16_t bottomOfBand = 875;
1342         int falseStation = -1;
1343
1344
1345         if (!fm->powerup)
1346         {
1347                 parm->err = FM_BADSTATUS;
1348                 return -EPERM;
1349         }
1350
1351         if (parm->space == FM_SPACE_100K)
1352         {
1353                 spaec = 1;
1354                 val &= (~((1<<0) | (1<<1)));
1355         }
1356         else if (parm->space == FM_SPACE_200K)
1357         {
1358                 spaec = 2;
1359                 val &= (~(1<<1));
1360                 val |= (1<<0);
1361         }
1362         else
1363         {
1364                 parm->err = FM_EPARM;
1365                 return -EPERM;
1366         }
1367
1368         if (parm->band == FM_BAND_UE)
1369         {
1370                 val &= (~((1<<2) | (1<<3)));
1371                 bottomOfBand = 875;
1372                 fm->min_freq = 875;
1373                 fm->max_freq = 1080;
1374         }
1375         else if (parm->band == FM_BAND_JAPAN) 
1376         {
1377                 val &= (~(1<<3));
1378                 val |= (1 << 2);
1379                 bottomOfBand = 760;
1380                 fm->min_freq = 760;
1381                 fm->max_freq = 910;
1382         }
1383         else if (parm->band == FM_BAND_JAPANW) {
1384                 val &= (~(1<<2));
1385                 val |= (1 << 3);
1386                 bottomOfBand = 760;
1387                 fm->min_freq = 760;
1388                 fm->max_freq = 1080;
1389         }
1390         else
1391         {
1392                 FM_ALERT("band:%d out of range\n", parm->band);
1393                 parm->err = FM_EPARM;
1394                 return -EPERM;
1395         }
1396
1397         if (parm->freq < fm->min_freq || parm->freq > fm->max_freq) {
1398                 FM_ALERT("freq:%d out of range\n", parm->freq);
1399                 parm->err = FM_EPARM;
1400                 return -EPERM;
1401         }
1402
1403         if (parm->seekth > 0x0B) {
1404                 FM_ALERT("seekth:%d out of range\n", parm->seekth);
1405                 parm->err = FM_EPARM;
1406                 return -EPERM;
1407         }
1408
1409         RDAFM_read(fm->chipAddr, 0x05, &tRegValue);
1410         tRegValue &= (~(0x7f<<8));
1411         //tRegValue |= ((parm->seekth & 0x7f) << 8);
1412         tRegValue |= ((0x8 & 0x7f) << 8);
1413         RDAFM_write(fm->chipAddr, 0x05, tRegValue);
1414
1415
1416 #ifdef FMDEBUG
1417         if (parm->seekdir == FM_SEEK_UP)
1418                 FM_DEBUG("seek %d up\n", parm->freq);
1419         else
1420                 FM_DEBUG("seek %d down\n", parm->freq);
1421 #endif
1422
1423         // (1) set hmute bit
1424         RDAFM_enable_hmute(fm->chipAddr);
1425
1426         tFreq = parm->freq;
1427
1428         do {
1429
1430                 if (parm->seekdir == FM_SEEK_UP)
1431                         tFreq += spaec;
1432                 else
1433                         tFreq -= spaec;
1434
1435                 if (tFreq > fm->max_freq)
1436                         tFreq = fm->min_freq;
1437                 if (tFreq < fm->min_freq)
1438                         tFreq = fm->max_freq;
1439
1440                 val = (((tFreq - bottomOfBand+5) << 6) | (1 << 4) | (val & 0x0f));
1441                 RDAFM_write(fm->chipAddr, 0x03, val);
1442                 msleep(40);
1443                 ret = RDAFM_read(fm->chipAddr, 0x0B, &tRegValue);
1444                 if (ret < 0)
1445                 {
1446                         FM_DEBUG("fm_seek: read register failed tunning freq = %4X\n", tFreq);
1447                         falseStation = -1;
1448                 }
1449                 else
1450                 {
1451                         if ((tRegValue & 0x0100) == 0x0100)
1452                                 falseStation = 0;
1453                         else
1454                                 falseStation = -1;
1455                 }
1456
1457                 if(falseStation == 0)
1458                         break;
1459
1460         }while(tFreq != parm->freq);
1461
1462
1463         //clear hmute
1464         RDAFM_clear_hmute(fm->chipAddr);
1465
1466         if (falseStation == 0) // seek successfully
1467         {    
1468                 parm->freq = tFreq;
1469                 FM_ALERT("fm_seek success, freq:%d\n", parm->freq);
1470                 parm->err = FM_SUCCESS;
1471
1472         }
1473         else
1474         {
1475                 FM_ALERT("fm_seek failed, invalid freq\n");
1476                 parm->err = FM_SEEK_FAILED;
1477                 ret = -1;
1478         }
1479
1480         return ret;
1481 }
1482
1483 /*
1484  *  fm_scan
1485  */
1486 static int  fm_scan(struct fm *fm, struct fm_scan_parm *parm)
1487 {
1488         int ret = 0;
1489         uint16_t tRegValue = 0;
1490         uint16_t scandir = RDA599X_FM_SCAN_UP; //scandir ËÑË÷·½Ïò
1491         uint8_t space = 1; 
1492
1493         if (!fm->powerup){
1494                 parm->err = FM_BADSTATUS;
1495                 return -EPERM;
1496         }
1497
1498         RDAFM_read(fm->chipAddr, 0x03, &tRegValue);
1499
1500         if (parm->space == FM_SPACE_100K){
1501                 space = 1;
1502                 tRegValue &= (~((1<<0) | (1<<1))); //set 03H's bit[1:0] to 00
1503         }else if (parm->space == FM_SPACE_200K) {
1504                 space = 2;
1505                 tRegValue &= (~(1<<1)); //clear bit[1]
1506                 tRegValue |= (1<<0);    //set bit[0]
1507         }else{
1508                 //default
1509                 space = 1;
1510                 tRegValue &= (~((1<<0) | (1<<1))); //set 03H's bit[1:0] to 00
1511         }
1512
1513         if(parm->band == FM_BAND_UE){
1514                 tRegValue &= (~((1<<2) | (1<<3)));
1515                 fm->min_freq = 875;
1516                 fm->max_freq = 1080;
1517         }else if(parm->band == FM_BAND_JAPAN){
1518                 tRegValue &= (~(1<<3));
1519                 tRegValue |= (1 << 2);
1520                 fm->min_freq = 760;
1521                 fm->max_freq = 900;
1522         }else if(parm->band == FM_BAND_JAPANW){
1523                 tRegValue &= (~(1<<2));
1524                 tRegValue |= (1 << 3);
1525                 fm->min_freq = 760;
1526                 fm->max_freq = 1080;
1527         }else{
1528                 parm->err = FM_EPARM;
1529                 return -EPERM;
1530         }
1531
1532         //set space and band
1533         RDAFM_write(fm->chipAddr, 0x03, tRegValue);
1534         msleep(40);
1535
1536
1537         if(RDAFM_Scan(fm->chipAddr, fm->min_freq, fm->max_freq, &(parm->freq), parm->ScanTBL, &(parm->ScanTBLSize), scandir, space)){
1538                 parm->err = FM_SUCCESS;
1539         }else{
1540                 parm->err = FM_SEEK_FAILED;
1541         }
1542
1543         return ret;
1544 }
1545
1546
1547 static int fm_setvol(struct fm *fm, uint32_t vol)
1548 {
1549         int ret = 0;
1550         uint16_t tRegValue = 0;
1551
1552         if (vol > 15)
1553                 vol = 15;
1554
1555         FM_DEBUG("fm_setvol:%d\n", vol);
1556
1557         ret = RDAFM_read(fm->chipAddr, 0x05, &tRegValue);
1558         if (ret)
1559                 return -EPERM;
1560         tRegValue &= ~(0x000f);
1561         tRegValue |= vol;
1562
1563         ret = RDAFM_write(fm->chipAddr, 0x05, tRegValue);
1564         if (ret)
1565                 return -EPERM;
1566
1567         return 0;
1568 }
1569
1570 static int fm_getvol(struct fm *fm, uint32_t *vol)
1571 {
1572         int ret = 0;
1573         uint16_t tRegValue;
1574
1575         ret = RDAFM_read(fm->chipAddr, 0x05, &tRegValue);
1576         if (ret)
1577                 return -EPERM;
1578
1579         if (ret)
1580                 return -EPERM;
1581
1582         *vol = (tRegValue & 0x000F);
1583
1584         return 0;
1585 }
1586
1587 static int fm_getrssi(struct fm *fm, uint32_t *rssi)
1588 {
1589         int ret = 0;
1590         uint16_t tRegValue;
1591
1592         ret = RDAFM_read(fm->chipAddr, 0x0B, &tRegValue);
1593         if (ret)
1594                 return -EPERM;
1595
1596
1597         *rssi = (uint32_t)((tRegValue >> 9) & RDAFM_MASK_RSSI);
1598
1599         FM_DEBUG("rssi value:%d\n", *rssi);
1600
1601         return 0;
1602 }
1603
1604 /*
1605  *  fm_tune
1606  */
1607 static int fm_tune(struct fm *fm, struct fm_tune_parm *parm)
1608 {
1609         int ret;
1610         uint16_t val = 0;
1611         uint8_t space = 1;
1612         uint16_t bottomOfBand = 875;
1613
1614
1615         FM_DEBUG("%s\n", __func__);
1616
1617         if (!fm->powerup)
1618         {
1619                 parm->err = FM_BADSTATUS;
1620                 return -EPERM;
1621         } 
1622
1623         if (parm->space == FM_SPACE_100K)
1624         {
1625                 space = 1;
1626                 val &= (~((1<<0) | (1<<1)));
1627         }
1628         else if (parm->space == FM_SPACE_200K)
1629         {
1630                 space = 2;
1631                 val |= (1<<0);
1632                 val &= (~(1<<1));
1633         }
1634         else
1635         {
1636                 parm->err = FM_EPARM;
1637                 return -EPERM;
1638         }
1639
1640         if (parm->band == FM_BAND_UE)
1641         {
1642                 val &= (~((1<<2) | (1<<3)));
1643                 bottomOfBand = 875;
1644                 fm->min_freq = 875;
1645                 fm->max_freq = 1080;
1646         }
1647         else if (parm->band == FM_BAND_JAPAN) 
1648         {
1649                 val &= (~(1<<3));
1650                 val |= (1 << 2);
1651                 bottomOfBand = 760;
1652                 fm->min_freq = 760;
1653                 fm->max_freq = 910;
1654         }
1655         else if (parm->band == FM_BAND_JAPANW) {
1656                 val &= (~(1<<2));
1657                 val |= (1 << 3);
1658                 bottomOfBand = 760;
1659                 fm->min_freq = 760;
1660                 fm->max_freq = 1080;
1661         }
1662         else
1663         {
1664                 FM_ALERT("band:%d out of range\n", parm->band);
1665                 parm->err = FM_EPARM;
1666                 return -EPERM;
1667         }
1668
1669         if (parm->freq < fm->min_freq || parm->freq > fm->max_freq) {
1670                 FM_ALERT("freq:%d out of range\n", parm->freq);
1671                 parm->err = FM_EPARM;
1672                 return -EPERM;
1673         }
1674
1675         FM_DEBUG("fm_tune, freq:%d\n", parm->freq);
1676
1677
1678         val = (((parm->freq - bottomOfBand + 5) << 6) | (1 << 4) | (val & 0x0f));
1679
1680         ret = RDAFM_write(fm->chipAddr, 0x03, val);
1681         if (ret < 0)
1682         {
1683                 FM_ALERT("fm_tune write freq failed\n");
1684                 parm->err = FM_SEEK_FAILED;
1685                 return ret;
1686         }
1687         msleep(40);
1688
1689         return ret;
1690 }
1691
1692
1693 static int mt_fm_probe(struct platform_device *pdev)
1694 {
1695         int err = -1;
1696         FM_DEBUG("mt_fm_probe\n");
1697
1698         if ((err = fm_init()))
1699         {
1700                 FM_ALERT("fm_init ERR:%d\n", err);
1701         }   
1702
1703         return err;   
1704
1705
1706 static int mt_fm_remove(struct platform_device *pdev)
1707 {
1708         FM_DEBUG("mt_fm_remove\n");
1709
1710         struct fm *fm = g_fm_struct;
1711         if(fm)
1712         {    
1713                 fm_destroy(fm);
1714                 fm = NULL;
1715         }
1716
1717         return 0; 
1718 }
1719
1720
1721 static struct platform_driver mt_fm_dev_drv =
1722 {
1723         .probe   = mt_fm_probe,
1724         .remove  = mt_fm_remove,
1725         .driver = {
1726                 .name   = FM_NAME,
1727                 .owner  = THIS_MODULE,    
1728         }
1729 };
1730
1731 #if defined(MTK_MT6515)
1732 static struct platform_device mt_fm_device = {
1733         .name   = FM_NAME,
1734         .id = -1, 
1735 };
1736 #endif
1737
1738
1739 /*
1740  *  mt_fm_init
1741  */
1742 static int __init mt_fm_init(void)
1743 {
1744         int err = 0;
1745
1746         FM_DEBUG("mt_fm_init\n");
1747 #if defined(MTK_MT6515)
1748         err = platform_device_register(&mt_fm_device);
1749         if(err){
1750                 FM_DEBUG("platform_device_register  fail\n");
1751                 return err;
1752         }else{
1753                 FM_DEBUG("platform_device_register  success\n");
1754         }
1755 #endif
1756         err = platform_driver_register(&mt_fm_dev_drv);
1757         if (err)
1758         {
1759                 FM_DEBUG("platform_driver_register failed\n");
1760         }else{
1761                 FM_DEBUG("platform_driver_register success\n");
1762         }
1763
1764         return err;
1765 }
1766
1767 /*
1768  *  mt_fm_exit
1769  */
1770 static void __exit mt_fm_exit(void)
1771 {
1772         FM_DEBUG("mt_fm_exit\n");
1773         platform_driver_unregister(&mt_fm_dev_drv);
1774 #if defined(MTK_MT6515)
1775         platform_device_unregister(&mt_fm_device);
1776 #endif
1777 }
1778
1779 module_init(mt_fm_init);
1780 module_exit(mt_fm_exit);
1781
1782 MODULE_LICENSE("GPL");
1783 MODULE_DESCRIPTION("MediaTek FM Driver");
1784 MODULE_AUTHOR("William Chung <William.Chung@MediaTek.com>");