add MTK-combo-module,continue with commit 17f39ed917874e77e80411f33faba1b7ee8138c8
[firefly-linux-kernel-4.4.55.git] / drivers / mtk_wcn_combo / drv_fm / public / mt6620_rds.c
1 /* Copyright Statement:
2  *
3  * This software/firmware and related documentation ("MediaTek Software") are
4  * protected under relevant copyright laws. The information contained herein
5  * is confidential and proprietary to MediaTek Inc. and/or its licensors.
6  * Without the prior written permission of MediaTek inc. and/or its licensors,
7  * any reproduction, modification, use or disclosure of MediaTek Software,
8  * and information contained herein, in whole or in part, shall be strictly prohibited.
9  *
10  * MediaTek Inc. (C) 2010. All rights reserved.
11  *
12  * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
13  * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
14  * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
15  * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
18  * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
19  * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
20  * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
21  * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
22  * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
23  * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
24  * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
25  * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
26  * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
27  * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
28  * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
29  * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
30  *
31  * The following software/firmware and/or related documentation ("MediaTek Software")
32  * have been modified by MediaTek Inc. All revisions are subject to any receiver's
33  * applicable license agreements with MediaTek Inc.
34  */
35
36 #include <linux/module.h>
37 #include <linux/kernel.h>
38 #include <linux/init.h>
39 #include <linux/delay.h> // udelay()
40 #include <linux/device.h> // device_create()
41 #include <linux/platform_device.h>
42 #include <linux/i2c.h>
43 #include <linux/cdev.h>
44 #include <linux/fs.h>
45
46 #include <asm/uaccess.h> // get_user()
47
48 #include "fm.h"
49 #include "mt6620_fm.h"
50 #include "mt6620_fm_lib.h"
51
52 /******************************************************************************
53  * GLOBAL DATA
54  *****************************************************************************/
55 #define MT6620_RDS_BLER_TH1 90
56 #define MT6620_RDS_BLER_TH2 60
57 #define MT6620_RDS_BLER_C1  12
58 #define MT6620_RDS_BLER_C2  6
59 #define MT6620_RDS_BLER_T1  5000
60 #define MT6620_RDS_BLER_T2  5000
61
62 //FM_RDS_DATA_CRC_FFOST(0xB2)
63 #define FM_RDS_GDBK_IND_A        (0x08) 
64 #define FM_RDS_GDBK_IND_B        (0x04) 
65 #define FM_RDS_GDBK_IND_C        (0x02) 
66 #define FM_RDS_GDBK_IND_D        (0x01) 
67 #define FM_RDS_DCO_FIFO_OFST (0x01E0)
68 #define FM_RDS_READ_DELAY        (0x80)
69
70
71 /******************************************************************************
72  * GLOBAL VARIABLE
73  *****************************************************************************/
74 static bool bRDS_FirstIn = false;
75 static uint16_t RDS_Sync_Cnt = 0, RDS_Block_Reset_Cnt = 0;
76
77 extern int16_t _current_frequency;
78 uint32_t gBLER_CHK_INTERVAL = 5000;
79 static int16_t preAF_Num = 0;
80 static int16_t preAFON_Num = 0;
81 uint16_t GOOD_BLK_CNT = 0, BAD_BLK_CNT = 0;
82 uint8_t BAD_BLK_RATIO = 0;
83
84 #ifndef FM_ASSERT
85 #define FM_ASSERT(a) { \
86                         if ((a) == NULL) { \
87                                 printk("%s, invalid buf\n", __func__);\
88                                 return -ERR_INVALID_BUF; \
89                         } \
90                 }
91 #endif
92
93 #define RDS_RT_MULTI_REV_TH 16
94 enum
95 {
96     RDS_GRP_VER_A = 0,  //group version A
97     RDS_GRP_VER_B
98 };
99
100 typedef enum RDS_RT_STATE_MACHINE
101 {
102     RDS_RT_START = 0,
103     RDS_RT_DECISION,
104     RDS_RT_GETLEN,
105     RDS_RT_DISPLAY,
106     RDS_RT_FINISH,
107     RDS_RT_MAX
108 }RDS_RT_STATE_MACHINE;
109
110 typedef enum RDS_BLK_T
111 {
112     RDS_BLK_A = 0,
113     RDS_BLK_B,
114     RDS_BLK_C,
115     RDS_BLK_D,
116     RDS_BLK_MAX
117 }RDS_BLK_T;
118
119 static RDS_RT_STATE_MACHINE rt_state_machine = RDS_RT_START;
120
121 /******************************************************************************
122  * Local function extern
123  *****************************************************************************/
124 static int MT6620_RDS_enable(void);
125 static int MT6620_RDS_disable(void);
126 static int MT6620_RDS_Get_GoodBlock_Counter(uint16_t* pCnt);
127 static int MT6620_RDS_Get_BadBlock_Counter(uint16_t* pCnt);
128 static int MT6620_RDS_Reset_Block_Counter(void);
129 static int MT6620_RDS_Reset(void);
130 static int MT6620_RDS_Reset_Block(void);
131 static int MT6620_RDS_Init_Data(RDSData_Struct *pstRDSData);
132 static int MT6620_RDS_RetrieveGroup0(uint16_t *block_data, uint8_t SubType, RDSData_Struct *pstRDSData);
133 static int MT6620_RDS_RetrieveGroup1(uint16_t *block_data, uint8_t SubType, RDSData_Struct *pstRDSData);
134 static int MT6620_RDS_RetrieveGroup2(uint16_t *block_data, uint8_t SubType, RDSData_Struct *pstRDSData);
135 static int MT6620_RDS_RetrieveGroup4(uint16_t *block_data, uint8_t SubType, RDSData_Struct *pstRDSData);
136 static int MT6620_RDS_RetrieveGroup14(uint16_t *block_data, uint8_t SubType, RDSData_Struct *pstRDSData);
137 extern int MT6620_read(uint8_t addr, uint16_t *val);
138 extern int MT6620_write(uint8_t addr, uint16_t val);
139 extern int MT6620_set_bits(uint8_t addr, uint16_t bits, uint16_t mask);
140 extern int  Delayms(uint32_t data);
141 extern int  Delayus(uint32_t data);
142
143 /*
144  * rds_cnt_get
145  * To get rds group count form raw data
146  * If success return 0, else return error code
147 */
148 static int rds_cnt_get(struct rds_rx *rds_raw, int raw_size, int *cnt){
149     int ret = 0;
150     int gap = sizeof(rds_raw->cos) + sizeof(rds_raw->sin);
151
152     FM_ASSERT(rds_raw);
153     FM_ASSERT(cnt);
154     *cnt = (raw_size - gap)/sizeof(rds_packet_struct);
155     FM_LOG_INF(D_RDS,"group cnt=%d\n", *cnt);
156     
157     return ret;
158 }
159
160 /*
161  * rds_group_get
162  * To get rds group[n] data form raw data with index
163  * If success return 0, else return error code
164 */
165 static int rds_group_get(uint16_t *dst, struct rds_rx *raw, int idx){
166     int ret = 0;
167
168     FM_ASSERT(dst);
169     FM_ASSERT(raw);
170     if(idx > (MAX_RDS_RX_GROUP_CNT - 1)){
171         ret = -ERR_INVALID_PARA;
172         return ret;
173     }
174     dst[0] = raw->data[idx].blkA;
175     dst[1] = raw->data[idx].blkB;
176     dst[2] = raw->data[idx].blkC;
177     dst[3] = raw->data[idx].blkD;
178     dst[4] = raw->data[idx].crc;
179     dst[5] = raw->data[idx].cbc;
180     
181     FM_LOG_INF(D_RDS,"BLOCK:%04x %04x %04x %04x, CRC:%04x\n", dst[0], dst[1], dst[2], dst[3], dst[4]);
182     
183     return ret;
184 }
185
186 /*
187  * rds_checksum_check
188  * To check CRC rerult, if OK, *valid=TRUE, else *valid=FALSE
189  * If success return 0, else return error code
190 */
191 static int rds_checksum_check(uint16_t crc, int mask, bool *valid){
192     int ret = 0;
193
194     FM_ASSERT(valid);
195     if((crc & mask) == mask){
196         *valid = TRUE;
197     }else{
198         *valid = FALSE;
199     }  
200     
201     return ret;
202 }
203
204 /*
205  * rds_cbc_get - To get block_n's correct bit count form cbc
206  * @cbc, the group's correct bit count
207  * @blk, target the block 
208  * 
209  * If success, return block_n's cbc, else error code
210 */
211 static int rds_cbc_get(uint16_t cbc, enum RDS_BLK_T blk){
212     int ret = 0;
213
214     switch(blk){
215         case RDS_BLK_A:
216             ret = (cbc & 0xF000) >> 12;
217             break;
218         case RDS_BLK_B:
219             ret = (cbc & 0x0F00) >> 8;
220             break;
221         case RDS_BLK_C:
222             ret = (cbc & 0x00F0) >> 4;
223             break;
224         case RDS_BLK_D:
225             ret = (cbc & 0x000F) >> 0;
226             break;
227         default:
228             break;
229     }
230     FM_LOG_INF(D_RDS,"group cbc=0x%04x\n", cbc);
231     return ret;
232 }
233
234 /*
235  * rds_event_set
236  * To set rds event, and user space can use this flag to juge which event happened
237  * If success return 0, else return error code
238 */
239 static int rds_event_set(uint16_t *events, int event_mask){
240     int ret = 0;
241
242     FM_ASSERT(events);
243     *events |= event_mask;
244     
245     return ret;
246 }
247
248 /*
249  * rds_flag_set
250  * To set rds event flag, and user space can use this flag to juge which event happened
251  * If success return 0, else return error code
252 */
253 static int rds_flag_set(uint32_t *flags, int flag_mask){
254     int ret = 0;
255
256     FM_ASSERT(flags);
257     *flags |= flag_mask;
258     
259     return ret;
260 }
261
262 /*
263  * rds_group_type_get
264  * To get rds group type form blockB
265  * If success return 0, else return error code
266 */
267 static int rds_group_type_get(uint16_t crc, uint16_t blk, uint8_t *type, uint8_t *subtype){
268     int ret = 0;
269     bool valid = FALSE;
270
271     FM_ASSERT(type);
272     FM_ASSERT(subtype);
273     //to get the group type from block B
274     ret = rds_checksum_check(crc, FM_RDS_GDBK_IND_B, &valid);
275     if(valid == TRUE){
276         *type = (blk & 0xF000)>>12; //Group type(4bits)
277         *subtype = (blk & 0x0800)>>11; //version code(1bit), 0=vesionA, 1=versionB
278     }else{
279         FM_LOG_WAR(D_RDS,"Block1 CRC err\n");
280         return -ERR_RDS_CRC;
281     }
282     
283     FM_LOG_INF(D_RDS,"Type=%d, subtype:%s\n", (int)*type, *subtype ? "version B" : "version A");
284     return ret;
285 }
286
287 /*
288  * rds_group_counter_add
289  * @type -- group type, rang: 0~15
290  * @subtype -- sub group type, rang:0~1
291  *
292  * add group counter, group0a~group15b
293  * we use type value as the index
294  * If success return 0, else return error code
295 */
296 static int rds_group_counter_add(uint8_t type, uint8_t subtype, struct rds_group_cnt *gc)
297 {
298     FM_ASSERT(gc);
299
300     if(type > 15){
301         return -ERR_INVALID_PARA;
302     }
303     switch(subtype){
304         case RDS_GRP_VER_A:
305             gc->groupA[type]++;
306             break;
307         case RDS_GRP_VER_B:
308             gc->groupB[type]++;
309             break;
310         default:
311             return -ERR_INVALID_PARA;
312             break;
313     }
314     gc->total++;
315     FM_LOG_INF(D_RDS,"group counter:%d\n", (int)gc->total);
316     return 0;
317 }
318
319 /*
320  * rds_group_counter_get
321  *
322  * read group counter , group0a~group15b
323  * If success return 0, else return error code
324 */
325 extern int rds_group_counter_get(struct rds_group_cnt *dst, struct rds_group_cnt *src)
326 {
327     FM_ASSERT(dst);
328     FM_ASSERT(src);
329     memcpy(dst, src, sizeof(struct rds_group_cnt));
330     return 0;
331 }
332
333 /*
334  * rds_group_counter_reset
335  *
336  * clear group counter to 0, group0a~group15b
337  * If success return 0, else return error code
338 */
339 extern int rds_group_counter_reset(struct rds_group_cnt *gc)
340 {
341     FM_ASSERT(gc);
342     memset(gc, 0, sizeof(struct rds_group_cnt));
343     return 0;
344 }
345
346 /*
347  * rds_group_pi_get
348  * To get rds group pi code form blockA
349  * If success return 0, else return error code
350 */
351 static int rds_group_pi_get(uint16_t crc, uint16_t blk, uint16_t *pi, bool *dirty){
352     int ret = 0;
353     bool valid = FALSE;
354
355     FM_ASSERT(pi);
356     FM_ASSERT(dirty);
357     
358     //to get the group pi code from block A
359     ret = rds_checksum_check(crc, FM_RDS_GDBK_IND_A, &valid);
360     if(valid == TRUE){
361         if(*pi != blk){
362                 //PI=program Identication
363             *pi = blk;
364                         *dirty = TRUE; // yes, we got new PI code
365         }else{
366             *dirty = FALSE; // PI is the same as last one
367         }
368     }else{
369         FM_LOG_WAR(D_RDS,"Block0 CRC err\n");
370         return -ERR_RDS_CRC;
371     }
372
373     FM_LOG_INF(D_RDS,"PI=0x%04x, %s\n", *pi, *dirty ? "new" : "old");
374     return ret;
375 }
376
377 /*
378  * rds_group_pty_get
379  * To get rds group pty code form blockB
380  * If success return 0, else return error code
381 */
382 static int rds_group_pty_get(uint16_t crc, uint16_t blk, uint8_t *pty, bool *dirty){
383     int ret = 0;
384     bool valid = FALSE;
385
386     FM_ASSERT(pty);
387     FM_ASSERT(dirty);
388     
389     //to get PTY code from block B
390     ret = rds_checksum_check(crc, FM_RDS_GDBK_IND_B, &valid);
391     if(valid == FALSE){
392         FM_LOG_WAR(D_RDS,"Block1 CRC err\n");
393         return -ERR_RDS_CRC;
394     }
395
396     if(*pty != ((blk & 0x03E0)>>5)){
397         //PTY=Program Type Code
398         *pty = (blk&0x03E0)>>5;
399         *dirty = TRUE; // yes, we got new PTY code
400     }else{
401         *dirty = FALSE; // PTY is the same as last one
402     }
403
404     FM_LOG_INF(D_RDS,"PTY=%d, %s\n", (int)*pty, *dirty ? "new" : "old");
405     return ret;
406 }
407
408 /*
409  * rds_group_tp_get
410  * To get rds group tp code form blockB
411  * If success return 0, else return error code
412 */
413 static int rds_group_tp_get(uint16_t crc, uint16_t blk, uint8_t *tp, bool *dirty){
414     int ret = 0;
415     bool valid = FALSE;
416
417     FM_ASSERT(tp);
418     FM_ASSERT(dirty);
419     
420     //to get TP code from block B
421     ret = rds_checksum_check(crc, FM_RDS_GDBK_IND_B, &valid);
422     if(valid == FALSE){
423         FM_LOG_WAR(D_RDS,"Block1 CRC err\n");
424         return -ERR_RDS_CRC;
425     }
426
427     if(*tp != ((blk&0x0400)>>10)){
428         //Tranfic Program Identification
429         *tp = (blk&0x0400)>>10;
430         *dirty = TRUE; // yes, we got new TP code
431     }else{
432         *dirty = FALSE; // TP is the same as last one
433     }
434
435     FM_LOG_INF(D_RDS,"TP=%d, %s\n", (int)*tp, *dirty ? "new" : "old");
436     return ret;
437 }
438
439 /*
440  * rds_group0_ta_get
441  * To get rds group ta code form blockB
442  * If success return 0, else return error code
443 */
444 static int rds_group0_ta_get(uint16_t blk, uint8_t *ta, bool *dirty){
445     int ret = 0;
446
447     FM_ASSERT(ta);
448     FM_ASSERT(dirty);
449     //TA=Traffic Announcement code
450     if(*ta != ((blk & 0x0010)>>4)){
451                 *ta = (blk & 0x0010)>>4;                        
452                 *dirty = TRUE; // yes, we got new TA code       
453         }else{
454             *dirty = FALSE; // TA is the same as last one
455         }
456
457     FM_LOG_INF(D_G0,"TA=%d, %s\n", (int)*ta, *dirty ? "new" : "old");
458     return ret;
459 }
460
461 /*
462  * rds_group0_music_get
463  * To get music-speech switch code form blockB
464  * If success return 0, else return error code
465 */
466 static int rds_group0_music_get(uint16_t blk, uint8_t *music, bool *dirty){
467     int ret = 0;
468
469     FM_ASSERT(music);
470     FM_ASSERT(dirty);
471     //M/S=music speech switch code
472     if(*music != ((blk & 0x0008)>>3)){
473                 *music = (blk & 0x0008)>>3;                     
474                 *dirty = TRUE; // yes, we got new music code    
475         }else{
476             *dirty = FALSE; // music  is the same as last one
477         }
478
479     FM_LOG_INF(D_G0,"Music=%d, %s\n", (int)*music, *dirty ? "new" : "old");
480     return ret;
481 }
482
483 /*
484  * rds_group2_rt_addr_get
485  * To get rt addr form blockB
486  * If success return 0, else return error code
487 */
488 static int rds_group2_rt_addr_get(uint16_t blk, uint8_t *addr){
489     int ret = 0;
490
491     FM_ASSERT(addr);
492     *addr = (uint8_t)blk & 0x0F;
493     
494     FM_LOG_INF(D_G2,"addr=0x%02x\n", *addr);
495     return ret;
496 }
497
498 static int rds_group2_txtAB_get(uint16_t blk, uint8_t *txtAB, bool *dirty){
499     int ret = 0;
500
501     FM_ASSERT(txtAB);
502     FM_ASSERT(dirty);
503
504     if(*txtAB != ((blk&0x0010)>>4)){
505                 *txtAB = (blk&0x0010)>>4;
506         *dirty = TRUE; // yes, we got new txtAB code
507     }else{
508         *dirty = FALSE; // txtAB is the same as last one
509     }
510     
511     FM_LOG_INF(D_G2,"txtAB=%d, %s\n", *txtAB, *dirty ? "new" : "old");
512     return ret;
513 }
514
515 static int rds_group2_rt_get(uint16_t crc, uint8_t subtype, uint16_t blkC, uint16_t blkD, uint8_t addr, uint8_t *buf){
516     int ret = 0;
517     bool valid = FALSE;
518     int idx = 0;
519
520     FM_ASSERT(buf);
521     //text segment addr rang 0~15
522     if(addr > 0xFF){
523         FM_LOG_ERR(D_RDS,"addr invalid(0x%02x)\n", addr);
524         ret = -ERR_INVALID_PARA;
525         return ret;
526     }
527     switch(subtype){
528         case RDS_GRP_VER_A:
529             idx = 4*addr;
530             ret = rds_checksum_check(crc, FM_RDS_GDBK_IND_C | FM_RDS_GDBK_IND_D, &valid);
531             if(valid == TRUE){
532                 buf[idx] = blkC>>8;
533                 buf[idx+1] = blkC&0xFF;
534                 buf[idx+2] = blkD>>8;
535                 buf[idx+3] = blkD&0xFF;
536             }else{
537                 FM_LOG_ERR(D_RDS,"rt crc check err\n");
538                 ret = -ERR_RDS_CRC;
539             }
540             break;
541         case RDS_GRP_VER_B:
542             idx = 2*addr;
543             ret = rds_checksum_check(crc, FM_RDS_GDBK_IND_D, &valid);
544             if(valid == TRUE){
545                 buf[idx] = blkD>>8;
546                 buf[idx+1] = blkD&0xFF;
547             }else{
548                 FM_LOG_ERR(D_RDS,"rt crc check err\n");
549                 ret = -ERR_RDS_CRC;
550             }
551             break;
552         default:
553             break;
554     }
555     
556     FM_LOG_INF(D_G2,"addr[%02x]:0x%02x 0x%02x 0x%02x 0x%02x\n", addr, buf[idx], buf[idx+1], buf[idx+2], buf[idx+3]);
557     return ret;
558 }
559
560 static int rds_group2_rt_get_len(uint8_t subtype, int pos, int *len){
561     int ret = 0;
562
563     FM_ASSERT(len);
564     if(subtype == RDS_GRP_VER_A){
565         *len = 4*(pos+1);
566     }else{
567         *len = 2*(pos+1);
568     }
569     
570     return ret;
571 }
572
573 /*
574  * rds_group2_rt_cmp
575  * this function is the most importent flow for RT parsing
576  * 1.Compare fresh buf with once buf per byte, if eque copy this byte to twice buf, else copy it to once buf
577  * 2.Check wether we got a full segment, for typeA if copyed 4bytes to twice buf, for typeB 2bytes copyed to twice buf
578  * 3.Check wether we got the end of RT, if we got 0x0D
579  * 4.If we got the end, then caculate the RT lenth
580  * If success return 0, else return error code
581 */
582 static int rds_group2_rt_cmp(uint8_t addr, uint16_t cbc, uint8_t subtype, uint8_t *fresh, 
583                 uint8_t *once, uint8_t *twice, bool *valid, bool *end, int *len){
584     int ret = 0;
585     int i = 0;
586     int j = 0; 
587     int cnt = 0;
588
589     FM_ASSERT(fresh);
590     FM_ASSERT(once);
591     FM_ASSERT(twice);
592     FM_ASSERT(valid);
593     FM_ASSERT(end);
594
595     j = (subtype == RDS_GRP_VER_A) ? 4 : 2; // RT segment width
596     if(subtype == RDS_GRP_VER_A){
597         if(rds_cbc_get(cbc, RDS_BLK_C) == 0){
598             once[j*addr+0] = fresh[j*addr+0];
599             once[j*addr+1] = fresh[j*addr+1];
600         }
601         if(rds_cbc_get(cbc, RDS_BLK_D) == 0){
602             once[j*addr+2] = fresh[j*addr+2];
603             once[j*addr+3] = fresh[j*addr+3];
604         }
605     }else if(subtype == RDS_GRP_VER_B){
606         if(rds_cbc_get(cbc, RDS_BLK_D) == 0){
607             once[j*addr+0] = fresh[j*addr+0];
608             once[j*addr+1] = fresh[j*addr+1];
609         }
610     }
611     
612     for(i = 0; i < j; i++){
613         if(fresh[j*addr+i] == once[j*addr+i]){
614             twice[j*addr+i] = once[j*addr+i]; //get the same byte 2 times
615             cnt++;
616         }else{
617             once[j*addr+i] = fresh[j*addr+i]; //use new val
618         }
619
620         //if we got 0x0D twice, it means a RT end
621         if(twice[j*addr+i] == 0x0D){
622             *end = TRUE;
623             *len = j*addr+i+1; //record the length of RT
624         }
625     }               
626
627     //check if we got a valid segment 4bytes for typeA, 2bytes for typeB
628     if(cnt == j){
629         *valid = TRUE;
630     }else{
631         *valid = FALSE;
632     }
633     FM_LOG_INF(D_G2,"RT seg=%s\n", *valid == TRUE ? "TRUE" : "FALSE");
634     FM_LOG_INF(D_G2,"RT end=%s\n", *end == TRUE ? "TRUE" : "FALSE");
635     FM_LOG_INF(D_G2,"RT len=%d\n", *len);
636     return ret;
637 }
638
639 static uint16_t rds_group2_rt_addr_bitmap_get(uint16_t bitmap){
640     return bitmap;
641 }
642
643 static int rds_group2_rt_addr_bitmap_get_pos(uint16_t bitmap){
644     int i = 15;
645     while(!(bitmap & (1<<i)) && (i > -1)){      
646         i--;
647     }
648     return i;
649 }
650
651 #if 0
652 static bool rds_group2_rt_addr_bitmap_test(uint16_t bitmap, uint8_t addr){
653     return (bitmap & (1<<addr)) ? TRUE : FALSE;
654 }
655 #endif
656
657 static int rds_group2_rt_addr_bitmap_clear(uint16_t *bitmap, int *bm_cnt){
658     int ret = 0;
659
660     FM_ASSERT(bitmap);
661     FM_ASSERT(bm_cnt);
662     *bitmap = 0x0000;
663     *bm_cnt = 0;
664     return ret;
665 }
666
667 /*
668  * rds_group2_rt_addr_bitmap_cmp - compare two bitmaps
669  * @bitmap1
670  * @bitmap2
671  * If bitmap1 > bitmap2, return positive(+)
672  * If bitmap1 = bitmap2, return 0
673  * If bitmap1 < bitmap2, return nagotive(-)
674  */
675 static int rds_group2_rt_addr_bitmap_cmp(uint16_t bitmap1, uint16_t bitmap2)
676 {
677     return (int)(bitmap1 - bitmap2);
678 }
679
680 static int rds_group2_rt_addr_bitmap_set(uint16_t *bitmap, int *bm_cnt, uint8_t addr){
681     int ret = 0;
682     uint16_t bm_old = 0;
683
684     FM_ASSERT(bitmap);
685     FM_ASSERT(bm_cnt);
686     //text segment addr rang 0~15
687     if(addr > 0xFF){
688         FM_LOG_ERR(D_RDS,"addr invalid(0x%02x)\n", addr);
689         ret = -ERR_INVALID_PARA;
690         return ret;
691     }
692     bm_old = *bitmap;
693     *bitmap |= (1<<addr); //set bitmap
694     if(!rds_group2_rt_addr_bitmap_cmp(bm_old, *bitmap)){
695         (*bm_cnt)++;  // multi get a segment
696     }else if(*bm_cnt > 0){
697         (*bm_cnt)--;
698     }
699     FM_LOG_NTC(D_G2,"RT bitmap=0x%04x, bmcnt=%d\n", *bitmap, *bm_cnt);
700     return ret;
701 }
702
703 static RDS_RT_STATE_MACHINE rds_rt_state_get(void){
704     return rt_state_machine;
705 }
706
707 static RDS_RT_STATE_MACHINE rds_rt_state_set(RDS_RT_STATE_MACHINE state_new){
708     rt_state_machine = state_new;
709     return rt_state_machine;
710 }
711
712 #if 0
713 static bool rds_group2_is_rt_finished(uint16_t *event){
714     FM_ASSERT(event);
715     if(*event&RDS_EVENT_LAST_RADIOTEXT){
716         return TRUE;
717     }else{
718         return FALSE;
719     }
720 }
721 #endif
722
723 static int MT6620_RDS_enable(void)
724 {
725     uint16_t page;
726     int ret = 0;
727     
728     if((ret = MT6620_read(FM_MAIN_PGSEL, &page)))
729         return ret;
730
731         if((ret = MT6620_write(0x9F, 0x0003)))
732         return ret;
733         if((ret = MT6620_write(0xCB, 0xE016)))
734         return ret;
735         if((ret = MT6620_write(0x9F, 0x0000)))
736         return ret;
737         if((ret = MT6620_write(0x63, 0x0491)))
738         return ret;
739         if((ret = MT6620_set_bits(0x6B, 0x2000, 0xFFFF)))
740         return ret;
741
742     ret = MT6620_write(FM_MAIN_PGSEL, page);
743
744     return ret;
745 }
746
747 static int MT6620_RDS_disable(void)
748 {
749     int ret = 0;
750         if((ret = MT6620_set_bits(0x6B, 0x0000, 0xDFFF)))
751         return ret;
752         ret = MT6620_write(0x63, 0x0481);
753
754     return ret;
755 }
756
757 static int MT6620_RDS_Get_GoodBlock_Counter(uint16_t* pCnt)
758 {
759     uint16_t tmp_reg;
760     uint16_t page;
761     int ret = 0;
762
763     if(NULL == pCnt)
764         return -ERR_INVALID_BUF;
765     
766     if((ret = MT6620_read(FM_MAIN_PGSEL, &page)))
767         return ret;
768
769     if((ret = MT6620_write(0x9F, 0x0003)))
770         return ret;
771     if((ret = MT6620_read(0xC6, &tmp_reg)))
772         return ret; 
773
774     ret = MT6620_write(FM_MAIN_PGSEL, page);
775     
776     *pCnt = tmp_reg;
777     return ret;  
778 }
779
780 static int MT6620_RDS_Get_BadBlock_Counter(uint16_t* pCnt)
781 {
782     uint16_t tmp_reg;
783     uint16_t page;
784     int ret = 0;
785
786     if(NULL == pCnt)
787         return -ERR_INVALID_BUF;
788     
789     if((ret = MT6620_read(FM_MAIN_PGSEL, &page)))
790         return ret;
791
792     if((ret = MT6620_write(0x9F, 0x0003)))
793         return ret;
794     if((ret = MT6620_read(0xC7, &tmp_reg)))
795         return ret;
796
797     ret = MT6620_write(FM_MAIN_PGSEL, page);
798
799     *pCnt = tmp_reg;
800     return ret;  
801 }
802
803
804 static int MT6620_RDS_Reset_Block_Counter(void)
805 {
806     uint16_t page;
807     int ret = 0;
808     
809     if((ret = MT6620_read(FM_MAIN_PGSEL, &page)))
810         return ret;
811
812     if((ret = MT6620_write(0x9F, 0x0003)))
813         return ret;
814     if((ret = MT6620_write(0xC8, 0x0001)))
815         return ret;
816     if((ret = MT6620_write(0xC8, 0x0002)))
817         return ret;
818
819     ret = MT6620_write(FM_MAIN_PGSEL, page);
820
821     return ret;
822 }
823
824 static int MT6620_RDS_Reset(void)
825 {
826     uint16_t page;
827     int ret = 0;
828     
829     if((ret = MT6620_read(FM_MAIN_PGSEL, &page)))
830         return ret;
831
832     if((ret = MT6620_write(0x9F, 0x0003)))
833         return ret;
834     if((ret = MT6620_write(0xB0, 0x0001)))
835         return ret;
836
837     ret = MT6620_write(FM_MAIN_PGSEL, page);
838
839     return ret;
840 }
841
842 static int MT6620_RDS_Reset_Block(void)
843 {
844     uint16_t page;
845     int ret = 0;
846     
847     if((ret = MT6620_read(FM_MAIN_PGSEL, &page)))
848         return ret;
849
850     if((ret = MT6620_write(0x9F, 0x0003)))
851         return ret;
852     if((ret = MT6620_write(0xDD, 0x0001)))
853         return ret;
854
855     ret = MT6620_write(FM_MAIN_PGSEL, page);
856
857     return ret;
858 }
859
860 int MT6620_RDS_BlerCheck(struct fm *fm)
861 {
862         RDSData_Struct *pstRDSData = fm->pstRDSData;
863     uint16_t TOTAL_CNT;
864     int ret = 0;
865     
866         FM_LOG_DBG(D_BLKC,"+T:%d, MT6620_RDS_BlerCheck\n", jiffies_to_msecs(jiffies));
867         
868     if(pstRDSData->AF_Data.Addr_Cnt == 0xFF){
869             //AF List Finished
870             pstRDSData->event_status |= RDS_EVENT_AF;  //Need notfiy application
871             //loop pstRDSData->event_status then act 
872         if(pstRDSData->event_status != 0){
873             fm->RDS_Data_ready = true;
874             wake_up_interruptible(&fm->read_wait);
875             FM_LOG_DBG(D_BLKC,"RDS_EVENT_AF, trigger read\n");
876         }
877         }
878         
879         gBLER_CHK_INTERVAL = MT6620_RDS_BLER_T1;
880         if((ret = MT6620_RDS_Get_GoodBlock_Counter(&GOOD_BLK_CNT)))
881         return ret;
882         FM_LOG_DBG(D_BLKC,"-T:%d, GOOD_BLK_CNT:%d\n", jiffies_to_msecs(jiffies), GOOD_BLK_CNT);
883         if((ret = MT6620_RDS_Get_BadBlock_Counter(&BAD_BLK_CNT)))
884         return ret;
885         TOTAL_CNT = GOOD_BLK_CNT + BAD_BLK_CNT;
886         if((ret = MT6620_RDS_Reset_Block_Counter()))
887         return ret;
888         FM_LOG_DBG(D_BLKC,"BLER: TOTAL_CNT:%d BAD_BLK_CNT:%d, RDS_Sync_Cnt:%d\n", TOTAL_CNT, BAD_BLK_CNT, RDS_Sync_Cnt);
889         
890         if((GOOD_BLK_CNT==0)&&(BAD_BLK_CNT==0)){
891         BAD_BLK_RATIO = 0;
892     }else{
893         BAD_BLK_RATIO = (BAD_BLK_CNT*100)/TOTAL_CNT;
894     }
895
896         //MT6620_RDS_BLER_TH1 90
897         //MT6620_RDS_BLER_TH2 60
898         //MT6620_RDS_BLER_C1  12
899         //MT6620_RDS_BLER_C2  6
900         //MT6620_RDS_BLER_T2  5000
901         if((BAD_BLK_RATIO < MT6620_RDS_BLER_TH2)&&(RDS_Sync_Cnt > MT6620_RDS_BLER_C1)){
902                 gBLER_CHK_INTERVAL = MT6620_RDS_BLER_T2;
903                 if(RDS_Block_Reset_Cnt > 1)
904                         RDS_Block_Reset_Cnt--;
905         }else{
906                 if(BAD_BLK_RATIO > MT6620_RDS_BLER_TH1){
907                     //>90%
908                         if((ret = MT6620_RDS_Reset_Block_Counter()))
909                 return ret;
910                         RDS_Sync_Cnt = 0;   //need clear or not, Question, LCH.
911                         RDS_Block_Reset_Cnt++;
912                         if((RDS_Block_Reset_Cnt > MT6620_RDS_BLER_C2)||bRDS_FirstIn){
913                 if(bRDS_FirstIn)
914                                     bRDS_FirstIn = false;
915                                 if((ret = MT6620_RDS_Reset()))
916                     return ret;
917                                 RDS_Block_Reset_Cnt = 0;
918                                 FM_LOG_DBG(D_BLKC,"RDS Reset, blk_cnt:%d, RDS_FirstIn:%d\n", RDS_Block_Reset_Cnt, bRDS_FirstIn);
919                         }else if(TOTAL_CNT > 12){
920                             //LCH question 2, why 12???
921                                 FM_LOG_DBG(D_BLKC,"RDS Block Reset: %x\n", RDS_Block_Reset_Cnt);
922                                 if((ret = MT6620_RDS_Reset_Block()))
923                     return ret;
924                         }
925                 }else{    
926                         RDS_Sync_Cnt++; //(60%-90%)     
927                         FM_LOG_DBG(D_BLKC,"RDS Sync Cnt: %d\n", RDS_Block_Reset_Cnt);   
928                         if(RDS_Block_Reset_Cnt > 1)
929                                 RDS_Block_Reset_Cnt--;
930                         if(RDS_Sync_Cnt > MT6620_RDS_BLER_C1){
931                                 gBLER_CHK_INTERVAL = MT6620_RDS_BLER_T2;
932                         }
933                 }
934         }
935
936     return ret;
937 }
938
939 static int MT6620_RDS_Init_Data(RDSData_Struct *pstRDSData)
940 {
941         uint8_t indx;
942     int ret = 0;
943
944     memset(pstRDSData, 0 ,sizeof(RDSData_Struct)); 
945     bRDS_FirstIn = true;
946
947     pstRDSData->PTY = 0xFF; //to avoid "rx PTY == 0" case, this will cause no PTY event
948         
949         for(indx = 0; indx < 64; indx++){
950                 pstRDSData->RT_Data.TextData[0][indx]=0x20;
951                 pstRDSData->RT_Data.TextData[1][indx]=0x20;             
952         }
953         for(indx = 0; indx < 8; indx++){
954                 pstRDSData->PS_Data.PS[0][indx] = '\0';
955                 pstRDSData->PS_Data.PS[1][indx] = '\0'; 
956                 pstRDSData->PS_Data.PS[2][indx] = '\0';
957                 pstRDSData->PS_ON[indx] = 0x20;
958         }       
959
960     return ret;
961 }
962
963 static int MT6620_RDS_RetrieveGroup0(uint16_t *block_data, uint8_t SubType, RDSData_Struct *pstRDSData)
964 {
965     uint8_t indx, indx2, DI_Code, DI_Flag, PS_Num, AF_H, AF_L, num;
966     int ret = 0;
967     bool valid = FALSE;
968     bool dirty = FALSE;
969     uint16_t *event = &pstRDSData->event_status;
970     uint32_t *flag = &pstRDSData->RDSFlag.flag_status;
971
972         ret = rds_checksum_check(block_data[4], FM_RDS_GDBK_IND_D, &valid);
973     if(valid == FALSE){
974         FM_LOG_WAR(D_G0,"Group0 BlockD crc err\n");
975         return -ERR_RDS_CRC;
976     }
977     
978     ret = rds_group0_ta_get(block_data[1], &pstRDSData->RDSFlag.TA, &dirty);
979     if(ret){
980         FM_LOG_WAR(D_G0,"get ta failed[ret=%d]\n", ret);
981     }else if(dirty == TRUE){
982         ret = rds_event_set(event, RDS_EVENT_FLAGS); // yes, we got new TA code
983         ret = rds_flag_set(flag, RDS_FLAG_IS_TA);
984         }
985
986     ret = rds_group0_music_get(block_data[1], &pstRDSData->RDSFlag.Music, &dirty);
987     if(ret){
988         FM_LOG_WAR(D_G0,"get music failed[ret=%d]\n", ret);
989     }else if(dirty == TRUE){
990         ret = rds_event_set(event, RDS_EVENT_FLAGS); // yes, we got new MUSIC code
991         ret = rds_flag_set(flag, RDS_FLAG_IS_MUSIC);
992     }
993
994         if((pstRDSData->Switch_TP)&&(pstRDSData->RDSFlag.TP)&&!(pstRDSData->RDSFlag.TA)){
995         ret = rds_event_set(event, RDS_EVENT_TAON_OFF);
996         }
997                 
998         if(!SubType){
999             //Type A
1000             ret = rds_checksum_check(block_data[4], FM_RDS_GDBK_IND_C, &valid);
1001         if(valid == FALSE){
1002             FM_LOG_WAR(D_G0,"Group0 BlockC crc err\n");
1003             return -ERR_RDS_CRC;
1004         }else{
1005                     AF_H = (block_data[2]&0xFF00)>>8;
1006                     AF_L= block_data[2]&0x00FF;
1007                     
1008                         if((AF_H > 224)&&(AF_H < 250)){
1009                             //Followed AF Number, see RDS spec Table 11, valid(224-249)
1010                             FM_LOG_DBG(D_G0,"RetrieveGroup0 AF_H:%d, AF_L:%d\n", AF_H, AF_L);
1011                                 pstRDSData->AF_Data.isAFNum_Get = 0;
1012                                 preAF_Num = AF_H - 224; //AF Number
1013                                 if(preAF_Num != pstRDSData->AF_Data.AF_Num){
1014                                         pstRDSData->AF_Data.AF_Num = preAF_Num;
1015                         }else{
1016                                     //Get the same AFNum two times
1017                                         pstRDSData->AF_Data.isAFNum_Get = 1;
1018                                 }
1019                                         
1020                                 if((AF_L < 205) && (AF_L > 0)){
1021                             //See RDS Spec table 10, valid VHF
1022                                         pstRDSData->AF_Data.AF[0][0] = AF_L+875; //convert to 100KHz
1023                                         FM_LOG_DBG(D_G0,"RetrieveGroup0 AF[0][0]:%d\n", pstRDSData->AF_Data.AF[0][0]);
1024                                         if((pstRDSData->AF_Data.AF[0][0]) != (pstRDSData->AF_Data.AF[1][0])){
1025                                                 pstRDSData->AF_Data.AF[1][0] = pstRDSData->AF_Data.AF[0][0];
1026                                     }else{                          
1027                                                 if(pstRDSData->AF_Data.AF[1][0] !=  _current_frequency)
1028                                                         pstRDSData->AF_Data.isMethod_A = 1;
1029                                                 else
1030                                                         pstRDSData->AF_Data.isMethod_A = 0;
1031                                         }
1032
1033                                         FM_LOG_DBG(D_G0,"RetrieveGroup0 isAFNum_Get:%d, isMethod_A:%d\n", pstRDSData->AF_Data.isAFNum_Get, pstRDSData->AF_Data.isMethod_A);
1034
1035                                         //only one AF handle
1036                                         if((pstRDSData->AF_Data.isAFNum_Get)&& (pstRDSData->AF_Data.AF_Num == 1)){
1037                                         pstRDSData->AF_Data.Addr_Cnt = 0xFF;
1038                                         pstRDSData->event_status |= RDS_EVENT_AF_LIST;
1039                                                 FM_LOG_DBG(D_G0,"RetrieveGroup0 RDS_EVENT_AF_LIST update\n");
1040                                     }                                   
1041                                 }                               
1042                         }                               
1043                         else if((pstRDSData->AF_Data.isAFNum_Get)&&(pstRDSData->AF_Data.Addr_Cnt != 0xFF)){
1044                 //AF Num correct
1045                 num = pstRDSData->AF_Data.AF_Num;
1046                                 num = num>>1;                           
1047                 FM_LOG_DBG(D_G0,"RetrieveGroup0 +num:%d\n", num);
1048                                 
1049                                 //Put AF freq into buffer and check if AF freq is repeat again
1050                             for(indx = 1; indx < (num+1); indx++){
1051                     if((AF_H == (pstRDSData->AF_Data.AF[0][2*num-1]))&&(AF_L == (pstRDSData->AF_Data.AF[0][2*indx]))){
1052                                             FM_LOG_ERR(D_G0|D_ALL,"RetrieveGroup0 AF same as indx:%d\n", indx);
1053                                                 break;
1054                                     }else if(!(pstRDSData->AF_Data.AF[0][2*indx-1])){
1055                                         //null buffer
1056                                                 pstRDSData->AF_Data.AF[0][2*indx-1] = AF_H+875; //convert to 100KHz
1057                                                 pstRDSData->AF_Data.AF[0][2*indx] = AF_L+875;
1058                                                 FM_LOG_DBG(D_G0,"RetrieveGroup0 AF[0][%d]:%d, AF[0][%d]:%d\n", 
1059                                    2*indx-1, pstRDSData->AF_Data.AF[0][2*indx-1], 2*indx, pstRDSData->AF_Data.AF[0][2*indx]);
1060                                                 break;
1061                                         }
1062                         }
1063                                 num = pstRDSData->AF_Data.AF_Num;
1064                                 FM_LOG_DBG(D_G0,"RetrieveGroup0 ++num:%d\n", num);
1065                             if(num > 0){
1066                                 if((pstRDSData->AF_Data.AF[0][num-1]) != 0){
1067                                                 num = num>>1;
1068                                                 FM_LOG_DBG(D_G0,"RetrieveGroup0 +++num:%d\n", num);
1069                                                 //arrange frequency from low to high:start
1070                                                 for(indx = 1; indx < num; indx++){
1071                                                         for(indx2 = indx+1; indx2 < (num+1); indx2++){
1072                                                                 AF_H = pstRDSData->AF_Data.AF[0][2*indx-1];
1073                                                                 AF_L = pstRDSData->AF_Data.AF[0][2*indx];
1074                                                                 if(AF_H > (pstRDSData->AF_Data.AF[0][2*indx2-1])){
1075                                                                         pstRDSData->AF_Data.AF[0][2*indx-1] = pstRDSData->AF_Data.AF[0][2*indx2-1];
1076                                                                         pstRDSData->AF_Data.AF[0][2*indx] = pstRDSData->AF_Data.AF[0][2*indx2];
1077                                                                         pstRDSData->AF_Data.AF[0][2*indx2-1] = AF_H;
1078                                                                         pstRDSData->AF_Data.AF[0][2*indx2] = AF_L;
1079                                                                 }else if(AF_H == (pstRDSData->AF_Data.AF[0][2*indx2-1])){
1080                                                                         if(AF_L > (pstRDSData->AF_Data.AF[0][2*indx2])){
1081                                                                                 pstRDSData->AF_Data.AF[0][2*indx-1] = pstRDSData->AF_Data.AF[0][2*indx2-1];
1082                                                                                 pstRDSData->AF_Data.AF[0][2*indx] = pstRDSData->AF_Data.AF[0][2*indx2];
1083                                                                                 pstRDSData->AF_Data.AF[0][2*indx2-1] = AF_H;
1084                                                                                 pstRDSData->AF_Data.AF[0][2*indx2] = AF_L;
1085                                                                         }
1086                                                                 }
1087                                                         }
1088                                                 }
1089                                                 //arrange frequency from low to high:end                                                
1090                                                 //compare AF buff0 and buff1 data:start
1091                                                 num = pstRDSData->AF_Data.AF_Num;
1092                                                 indx2 = 0;
1093                                                 
1094                                                 for(indx = 0; indx < num; indx++){
1095                             if((pstRDSData->AF_Data.AF[1][indx]) == (pstRDSData->AF_Data.AF[0][indx])){
1096                                                             if(pstRDSData->AF_Data.AF[1][indx] != 0)
1097                                                                         indx2++;
1098                                                     }else                                                   
1099                                                             pstRDSData->AF_Data.AF[1][indx] = pstRDSData->AF_Data.AF[0][indx];
1100                                             }
1101                                                 FM_LOG_DBG(D_G0,"RetrieveGroup0 indx2:%d, num:%d\n", indx2, num);
1102                                                 //compare AF buff0 and buff1 data:end                                           
1103                                                 if(indx2 == num){
1104                                                     pstRDSData->AF_Data.Addr_Cnt = 0xFF;
1105                                                     pstRDSData->event_status |= RDS_EVENT_AF_LIST;
1106                                                         FM_LOG_DBG(D_G0,"RetrieveGroup0 AF_Num:%d\n", pstRDSData->AF_Data.AF_Num);
1107                                                     for(indx = 0; indx < num; indx++){
1108                                                                 if((pstRDSData->AF_Data.AF[1][indx]) == 0){
1109                                                                     pstRDSData->AF_Data.Addr_Cnt = 0x0F;
1110                                                                     pstRDSData->event_status &= (~RDS_EVENT_AF_LIST);
1111                                                             }
1112                                                    }
1113                                             }
1114                                             else
1115                                                     pstRDSData->AF_Data.Addr_Cnt = 0x0F;
1116                                     }
1117                             }
1118                     }                   
1119             }
1120         }
1121                                 
1122         /*DI_Code[1:0]:   "00" = d3 *
1123           *               "01" = d2 *
1124           *               "10" = d1 *
1125           *               "11" = d0 */
1126                                 
1127         DI_Code = block_data[1]&0x0003;  //DI=decoder identification code.
1128         DI_Flag = (block_data[1]&0x0004)>>2;
1129                                   
1130         switch(DI_Code){
1131             case 3:
1132                     if(pstRDSData->RDSFlag.Stereo != DI_Flag){
1133                         pstRDSData->RDSFlag.Stereo = DI_Flag;
1134                         pstRDSData->event_status |= RDS_EVENT_FLAGS;
1135                         pstRDSData->RDSFlag.flag_status |= RDS_FLAG_IS_STEREO;
1136                 }
1137                     break;
1138         case 2:
1139                     if(pstRDSData->RDSFlag.Artificial_Head != DI_Flag){
1140                             pstRDSData->RDSFlag.Artificial_Head = DI_Flag;
1141                             pstRDSData->event_status |= RDS_EVENT_FLAGS;
1142                             pstRDSData->RDSFlag.flag_status |= RDS_FLAG_IS_ARTIFICIAL_HEAD;
1143                     }
1144                     break;
1145         case 1:
1146                     if(pstRDSData->RDSFlag.Compressed != DI_Flag){
1147                             pstRDSData->RDSFlag.Compressed = DI_Flag;
1148                             pstRDSData->event_status |= RDS_EVENT_FLAGS;
1149                             pstRDSData->RDSFlag.flag_status |= RDS_FLAG_IS_COMPRESSED;  
1150                 }
1151                 break;
1152         case 0:
1153                     if(pstRDSData->RDSFlag.Dynamic_PTY != DI_Flag){
1154                             pstRDSData->RDSFlag.Dynamic_PTY = DI_Flag;
1155                             pstRDSData->event_status |= RDS_EVENT_FLAGS;
1156                             pstRDSData->RDSFlag.flag_status |= RDS_FLAG_IS_DYNAMIC_PTY; 
1157                     }
1158                     break;              
1159         default:
1160                 break;                   
1161         }
1162                             
1163         PS_Num = block_data[1]&0x0003;  //Figure 12 Type 0 group.
1164     AF_H = pstRDSData->PS_Data.PS[0][2*PS_Num];
1165     AF_L = pstRDSData->PS_Data.PS[0][2*PS_Num+1];
1166     if((AF_H == (block_data[3])>>8)&&(AF_L == (block_data[3]&0xFF))){
1167             if((!((pstRDSData->event_status)&RDS_EVENT_PROGRAMNAME))&&((PS_Num == 0)||(pstRDSData->PS_Data.Addr_Cnt))){
1168             pstRDSData->PS_Data.PS[1][2*PS_Num]=(block_data[3])>>8;
1169                         pstRDSData->PS_Data.PS[1][2*PS_Num+1] = (block_data[3])&0xFF;                   
1170                         FM_LOG_DBG(D_G0,"RetrieveGroup0 PS second time, NUM:%x H:%x L:%x\n", 
1171                                       PS_Num, pstRDSData->PS_Data.PS[1][2*PS_Num], pstRDSData->PS_Data.PS[1][2*PS_Num+1]);
1172                         
1173                         //Need clear buff0, LCH question 1, should clear not not?
1174                         if((PS_Num == 0)&&(pstRDSData->PS_Data.Addr_Cnt == 0)){
1175                                 for(indx = 2; indx < 8; indx++){
1176                                         pstRDSData->PS_Data.PS[0][indx] = '\0'; //clear buff0
1177                                 }
1178                         }
1179                         pstRDSData->PS_Data.Addr_Cnt |= 1<<PS_Num;
1180                         FM_LOG_DBG(D_G0,"RetrieveGroup0, Addr_Cnt:%x\n", pstRDSData->PS_Data.Addr_Cnt);
1181                         if(pstRDSData->PS_Data.Addr_Cnt == 0x0F){
1182                             //Avoid PS transient:Start 
1183                                 num = 0;        
1184                                 for(indx = 0; indx < 8; indx++){
1185                                         if(pstRDSData->PS_Data.PS[0][indx] == pstRDSData->PS_Data.PS[1][indx])
1186                                                 num++;
1187                                 }
1188                                 pstRDSData->PS_Data.Addr_Cnt = 0;
1189                             //Avoid PS transient:END 
1190
1191                                 if(num == 8){
1192                     // get same data 2 times
1193                                     num = 0;
1194                                     for(indx = 0; indx < 8; indx++){
1195                                             if(pstRDSData->PS_Data.PS[1][indx] == pstRDSData->PS_Data.PS[2][indx])
1196                                                 num++;
1197                                     }
1198                                     //if(num != 8) //get same data 2 times, and not same as the last show. 
1199                                             pstRDSData->event_status |= RDS_EVENT_PROGRAMNAME;
1200                                             
1201                                         for(indx = 0; indx < 8; indx++){
1202                                                 pstRDSData->PS_Data.PS[2][indx] = pstRDSData->PS_Data.PS[1][indx];
1203                                                 pstRDSData->PS_Data.PS[1][indx] = '\0';
1204                                                 pstRDSData->PS_Data.PS[0][indx] = '\0';
1205                                         }
1206                                 }else{
1207                                         pstRDSData->PS_Data.Addr_Cnt |= 1<<PS_Num;
1208                                 }
1209                         }
1210                 }
1211         }
1212         else{
1213         pstRDSData->PS_Data.PS[0][2*PS_Num]=(block_data[3])>>8;
1214                 pstRDSData->PS_Data.PS[0][2*PS_Num+1] = (block_data[3])&0xFF;
1215                 FM_LOG_DBG(D_G0,"RetrieveGroup0 PS, NUM:%x H:%x L:%x\n", 
1216                               PS_Num, pstRDSData->PS_Data.PS[0][2*PS_Num], pstRDSData->PS_Data.PS[0][2*PS_Num+1]);
1217     }
1218     
1219         if((pstRDSData->event_status)&RDS_EVENT_PROGRAMNAME){
1220                 PS_Num = 0;
1221                 for(num = 0; num < 8;num++){
1222                         if(pstRDSData->PS_Data.PS[2][num] == '\0')
1223                             PS_Num |= 1<<num;
1224                 }
1225                 if(PS_Num == 0xFF){
1226                         FM_LOG_ERR(D_G0|D_ALL,"RDS PS Canncel event 0x08");
1227                         pstRDSData->event_status &= (~RDS_EVENT_PROGRAMNAME);
1228             }
1229         } 
1230
1231     return ret;
1232 }
1233
1234 static int MT6620_RDS_RetrieveGroup1(uint16_t *block_data, uint8_t SubType, RDSData_Struct *pstRDSData)
1235 {
1236         uint8_t variant_code = (block_data[2]&0x7000)>>12;
1237         int ret = 0;
1238     
1239         if(variant_code == 0){      
1240                 pstRDSData->Extend_Country_Code = (uint8_t)block_data[2]&0xFF;
1241                 FM_LOG_DBG(D_G1,"Extend_Country_Code:%d\n", pstRDSData->Extend_Country_Code);
1242         }else if(variant_code == 3){
1243                 pstRDSData->Language_Code = block_data[2]&0xFFF;
1244                 FM_LOG_DBG(D_G1,"Language_Code:%d\n", pstRDSData->Language_Code);
1245         }
1246                                 
1247         pstRDSData->Radio_Page_Code = block_data[1]&0x001F;
1248         pstRDSData->Program_Item_Number_Code = block_data[3];
1249
1250     return ret;
1251 }
1252
1253 #ifdef FM_RDS_G2_USE_OLD
1254 static bool PreTextABFlag;
1255
1256 static int MT6620_RDS_RetrieveGroup2(uint16_t *block_data, uint8_t SubType, RDSData_Struct *pstRDSData)
1257 {
1258     uint8_t TextAddr, indx, indx2, space, byte0, byte1;
1259         uint16_t addrcnt;
1260         int i = 0;
1261     int ret = 0;
1262     
1263         TextAddr = (uint8_t)block_data[1]&0x0F;
1264         
1265         if(pstRDSData->RDSFlag.Text_AB != ((block_data[1]&0x0010)>>4)){
1266                 pstRDSData->RDSFlag.Text_AB = (block_data[1]&0x0010)>>4;
1267                 pstRDSData->event_status |= RDS_EVENT_FLAGS;
1268                 pstRDSData->RDSFlag.flag_status |= RDS_FLAG_TEXT_AB;
1269         }
1270         FM_LOG_DBG(D_G2,"RT RetrieveGroup2 TextABFlag: %x --> %x\n", PreTextABFlag, pstRDSData->RDSFlag.Text_AB);
1271         
1272         if(PreTextABFlag != pstRDSData->RDSFlag.Text_AB){ // Text A/B changed, clear old RT, and get new RT
1273                 /*DDB:Some station don't send 0x0D, it just switch TextAB if it want to send next message.*/
1274                 if (pstRDSData->RT_Data.isRTDisplay == 0) {
1275                         FM_LOG_WAR(D_G2,"RT_Data.isRTDisplay == 0, and TextAB changed\n");
1276                         pstRDSData->event_status |= RDS_EVENT_LAST_RADIOTEXT; 
1277                         space = 0;
1278                         for(indx = 0; indx < 64; indx++){
1279                                 /*DDB:Why TextData[1][0] NOT TextData[2][0],  Because some station just send a message one time, and then change TextAB, send another message, SUCH As Beijing 90.0*/
1280                                 if(pstRDSData->RT_Data.TextData[1][indx] == 0x20)
1281                                         space++;
1282                         }       
1283                         if(space == 64)
1284                                 pstRDSData->event_status &= (~RDS_EVENT_LAST_RADIOTEXT);
1285
1286                         if (pstRDSData->event_status & RDS_EVENT_LAST_RADIOTEXT){
1287                                 /*DDB:Why TextData[1][0] NOT TextData[2][0],  Because some station just send a message one time, and then change TextAB, send another message, SUCH As Beijing 90.0*/
1288                                 memcpy(&(pstRDSData->RT_Data.TextData[3][0]), &(pstRDSData->RT_Data.TextData[1][0]), sizeof(pstRDSData->RT_Data.TextData[3]));
1289                                 FM_LOG_WAR(D_G2,"RT_Data.isRTDisplay = 1, no 0x0D case.\n");
1290                                 pstRDSData->RT_Data.isRTDisplay = 1;
1291                         }
1292                 }
1293
1294                 //to get Radio text length
1295                 pstRDSData->RT_Data.TextLength = 0;
1296                 i = 15;
1297                 while(!(pstRDSData->RT_Data.Addr_Cnt & (1<<i)) && (i > -1)){    
1298                         i--;
1299                 }
1300         if(!SubType){
1301                         pstRDSData->RT_Data.TextLength = 4*(i+1);
1302                 }else{
1303                         pstRDSData->RT_Data.TextLength = 2*(i+1);
1304                 }
1305         FM_LOG_INF(D_G2,"RDS RT Get Len: [AddrMap=0x%x] [Length=0x%x]\n", pstRDSData->RT_Data.Addr_Cnt, pstRDSData->RT_Data.TextLength);
1306                         
1307                 /*DDB, end*/
1308                 //clear the buffer because Text A/B changed
1309             memset(&(pstRDSData->RT_Data.TextData[0][0]), 0x20, sizeof(pstRDSData->RT_Data.TextData[0]));
1310                 memset(&(pstRDSData->RT_Data.TextData[1][0]), 0x20, sizeof(pstRDSData->RT_Data.TextData[1]));
1311         memset(&(pstRDSData->RT_Data.TextData[2][0]), 0x20, sizeof(pstRDSData->RT_Data.TextData[2]));           
1312                 PreTextABFlag = pstRDSData->RDSFlag.Text_AB;
1313                 pstRDSData->RT_Data.GetLength = 0;
1314                 pstRDSData->RT_Data.Addr_Cnt = 0;
1315                 //pstRDSData->RT_Data.isRTDisplay = 0;
1316         }
1317         
1318         if(!SubType){
1319             //Type A
1320                 //WCN_DBG(FM_ALERT|D_MAIN,"RetrieveGroup2 Type A RT TextAddr: 0x%x Text: 0x%x  0x%x", TextAddr, block_data[2], block_data[3]);
1321                 FM_LOG_NTC(D_G2,"%04x %04x %04x %04x %04x", block_data[0], block_data[1], block_data[2], block_data[3], block_data[4]);
1322                 pstRDSData->RT_Data.isTypeA = 1;
1323                 //to get the 4bytes RadioText
1324                 if(block_data[4]&(FM_RDS_GDBK_IND_C|FM_RDS_GDBK_IND_D)){
1325                         pstRDSData->RT_Data.TextData[0][4*TextAddr] = block_data[2]>>8;
1326                         pstRDSData->RT_Data.TextData[0][4*TextAddr+1] = block_data[2]&0xFF;
1327                         pstRDSData->RT_Data.TextData[0][4*TextAddr+2] = block_data[3]>>8;
1328                         pstRDSData->RT_Data.TextData[0][4*TextAddr+3] = block_data[3]&0xFF;
1329                         space = 0;
1330                         
1331             for(indx = 0; indx < 4;indx++){
1332                             byte0 = pstRDSData->RT_Data.TextData[0][4*TextAddr+indx];
1333                             byte1 = pstRDSData->RT_Data.TextData[1][4*TextAddr+indx];
1334                                 if (TextAddr == 0){
1335                                         //WCN_DBG(FM_ALERT|D_MAIN,"RT_Data.isRTDisplay = 0\n");
1336                                         pstRDSData->RT_Data.isRTDisplay = 0;
1337                                 }
1338                                 if((!(pstRDSData->event_status&RDS_EVENT_LAST_RADIOTEXT))&&(byte0 == byte1)){
1339                     //get the same byte 2 times
1340                                         space++;
1341                                         pstRDSData->RT_Data.TextData[2][4*TextAddr+indx] = byte0;
1342                                 }else{
1343                                         pstRDSData->RT_Data.TextData[1][4*TextAddr+indx] = byte0;
1344                                 }                                       
1345                         }
1346                         
1347                         if(space == 4){
1348                 addrcnt = pstRDSData->RT_Data.Addr_Cnt;
1349                                 pstRDSData->RT_Data.Addr_Cnt |= (1<<TextAddr);
1350                                 FM_LOG_DBG(D_G2,"RetrieveGroup2 RT addrcnt:%d, RT_Data.Addr_Cnt:%d\n", addrcnt, pstRDSData->RT_Data.Addr_Cnt);
1351                                 
1352                                 if(addrcnt == pstRDSData->RT_Data.Addr_Cnt){
1353                                     pstRDSData->RT_Data.BufCnt++;
1354                                 }else if(pstRDSData->RT_Data.BufCnt > 0){
1355                                         pstRDSData->RT_Data.BufCnt--;
1356                         }
1357                         }
1358                 } else {
1359                         FM_LOG_ERR(D_G2|D_ALL,"RT %04x %04x %04x %04x %04x CRC error.", block_data[0], block_data[1], block_data[2], block_data[3], block_data[4]);
1360                 }
1361                 for(indx = 0; indx < 4; indx++){
1362                         if(pstRDSData->RT_Data.TextData[2][4*TextAddr+indx] == 0x0D){
1363                     pstRDSData->RT_Data.TextLength = 4*TextAddr+indx+1; //Add terminate charater
1364                                 pstRDSData->RT_Data.TextData[2][4*TextAddr+indx] = '\0';
1365                                 pstRDSData->RT_Data.GetLength = 1;
1366                 }else if((4*TextAddr+indx) == 63 && pstRDSData->RT_Data.Addr_Cnt == 0xffff){
1367                             //type A full data. /*add by dongbo, make sure it's TextData[2], Not TextData[1]*/
1368                             pstRDSData->RT_Data.TextLength = 4*TextAddr+indx+1;  //no terminal character
1369                                 pstRDSData->RT_Data.GetLength = 1;
1370                         }
1371         }
1372         }else{
1373             //FM_LOG_DBG(D_MAIN,"RetrieveGroup2 Type B RT NUM: 0x%x Text: 0x%x", TextAddr, block_data[3]);
1374                 FM_LOG_DBG(D_G2,"RT %04x %04x %04x %04x %04x", block_data[0], block_data[1], block_data[2], block_data[3], block_data[4]);
1375                 pstRDSData->RT_Data.isTypeA = 0;
1376                 if(block_data[4]&FM_RDS_GDBK_IND_D){
1377             pstRDSData->RT_Data.TextData[0][2*TextAddr] = block_data[3]>>8;
1378                     pstRDSData->RT_Data.TextData[0][2*TextAddr+1] = block_data[3]&0xFF;
1379                         space = 0;
1380                         
1381                     for(indx = 0; indx < 2; indx++){
1382                         byte0 = pstRDSData->RT_Data.TextData[0][2*TextAddr+indx];
1383                             byte1 = pstRDSData->RT_Data.TextData[1][2*TextAddr+indx];
1384                                 
1385                                 if((!((pstRDSData->event_status)&RDS_EVENT_LAST_RADIOTEXT))&&(byte0 == byte1)){
1386                                         space++;
1387                                         pstRDSData->RT_Data.TextData[2][2*TextAddr+indx] = byte0;
1388                                 }else{
1389                                         pstRDSData->RT_Data.TextData[1][2*TextAddr+indx] = byte0;
1390                                 }
1391                         }
1392                         if(space == 2){
1393                             addrcnt = pstRDSData->RT_Data.Addr_Cnt;
1394                                 pstRDSData->RT_Data.Addr_Cnt |= (1<<TextAddr);
1395                                 FM_LOG_DBG(D_G2,"RT RetrieveGroup2 RT B addrcnt: 0x%x, RT_Data.Addr_Cnt: 0x%x\n", addrcnt, pstRDSData->RT_Data.Addr_Cnt);
1396                                 
1397                 if(addrcnt == pstRDSData->RT_Data.Addr_Cnt){
1398                                     pstRDSData->RT_Data.BufCnt++;
1399                                 }else if(pstRDSData->RT_Data.BufCnt > 0){
1400                                         pstRDSData->RT_Data.BufCnt--;
1401                                 }
1402             }
1403                 } else {
1404                         FM_LOG_DBG(D_G2,"RT %04x %04x %04x %04x %04x CRC error.", block_data[0], block_data[1], block_data[2], block_data[3], block_data[4]);
1405                 }
1406                 
1407                 for(indx = 0; indx < 2; indx++){
1408                         if((pstRDSData->RT_Data.TextData[2][2*TextAddr+indx]) == 0x0D){
1409                             //0x0D=end code
1410                             pstRDSData->RT_Data.TextLength = 2*TextAddr+indx+1;  //Add terminate charater
1411                                 pstRDSData->RT_Data.TextData[2][2*TextAddr+indx] = '\0';
1412                                 pstRDSData->RT_Data.GetLength = 1;
1413                         }else if((2*TextAddr+indx) == 31){
1414                             //full data
1415                             pstRDSData->RT_Data.TextLength = 2*TextAddr+indx+1;  //Add terminate charater
1416                 pstRDSData->RT_Data.TextData[2][2*TextAddr+indx] = '\0';
1417                                 pstRDSData->RT_Data.GetLength = 1;
1418                         }
1419                 }               
1420         }
1421
1422     //Check if text is fully received
1423         indx = TextAddr;
1424         if(pstRDSData->RT_Data.GetLength == 1){
1425                 addrcnt = 0xFFFF>>(0x0F-indx);
1426         }else if(pstRDSData->RT_Data.BufCnt > 100){
1427             pstRDSData->RT_Data.BufCnt = 0;
1428             for(indx = 15; indx >= 0; indx--){
1429                 addrcnt = (pstRDSData->RT_Data.Addr_Cnt)&(1<<indx);
1430                 if(addrcnt)
1431                     break;
1432                 }
1433                 
1434                 //get valid radio text length
1435                 if (pstRDSData->RT_Data.isTypeA){
1436                     for(indx2 = 0; indx2 < 4; indx2++){
1437                         if(pstRDSData->RT_Data.TextData[2][4*indx+indx2] == 0x0D){
1438                                     pstRDSData->RT_Data.TextLength = 4*indx+indx2+1;
1439                                         pstRDSData->RT_Data.TextData[2][4*indx+indx2] = '\0';
1440                     }
1441                     }
1442             }else{
1443                 for(indx2 = 0; indx2 < 2; indx2++){
1444                         if(pstRDSData->RT_Data.TextData[2][2*indx+indx2] == 0x0D){
1445                                     pstRDSData->RT_Data.TextLength = 2*indx+indx2+1;
1446                                         pstRDSData->RT_Data.TextData[2][2*indx+indx2] = '\0';
1447                     }
1448                     }
1449                 
1450             }
1451                 addrcnt = 0xFFFF>>(0x0F-indx);
1452         }else{
1453                 if(pstRDSData->RT_Data.TextLength > 64){
1454                         pstRDSData->RT_Data.TextLength = 64;
1455                 }
1456                 addrcnt = 0xFFFF;
1457         }
1458         
1459     FM_LOG_NTC(D_G2,"RetrieveGroup2 RDS RT: Addr_Cnt: 0x%x Length: 0x%x addrcnt: 0x%x\n", pstRDSData->RT_Data.Addr_Cnt, pstRDSData->RT_Data.TextLength, addrcnt);
1460
1461         if(((((pstRDSData->RT_Data.Addr_Cnt)&addrcnt) == addrcnt)||((TextAddr == 0x0f) && (pstRDSData->RT_Data.Addr_Cnt == 0xffff)))){          
1462         //&&(pstRDSData->RT_Data.isRTDisplay == 0))
1463         pstRDSData->RT_Data.Addr_Cnt = 0;
1464                 //pstRDSData->RT_Data.isRTDisplay = 1;
1465                 pstRDSData->event_status |= RDS_EVENT_LAST_RADIOTEXT; 
1466                 FM_LOG_DBG(D_G2,"RT RetrieveGroup2 isRTDisplay:%d\n", pstRDSData->RT_Data.isRTDisplay);
1467                 space = 0;
1468                 for(indx = 0; indx < 64; indx++){
1469                         if(pstRDSData->RT_Data.TextData[2][indx] == 0x20)
1470                                 space++;
1471             }   
1472             if(space == 64)
1473             pstRDSData->event_status &= (~RDS_EVENT_LAST_RADIOTEXT);
1474
1475                 memset(&(pstRDSData->RT_Data.TextData[1][0]), 0x20, sizeof(pstRDSData->RT_Data.TextData[1]));
1476                 memset(&(pstRDSData->RT_Data.TextData[0][0]), 0x20, sizeof(pstRDSData->RT_Data.TextData[0]));
1477
1478                 if (pstRDSData->event_status & RDS_EVENT_LAST_RADIOTEXT){
1479                         memcpy(&(pstRDSData->RT_Data.TextData[3][0]), &(pstRDSData->RT_Data.TextData[2][0]), sizeof(pstRDSData->RT_Data.TextData[3]));
1480                         FM_LOG_WAR(D_G2,"RT_Data.isRTDisplay = 1\n");
1481                         pstRDSData->RT_Data.isRTDisplay = 1;
1482                 }
1483     }
1484
1485     return ret;
1486 }
1487 #else
1488 static int MT6620_RDS_RetrieveGroup2(uint16_t *source, uint8_t subtype, RDSData_Struct *target)
1489 {
1490     int ret = 0;
1491     uint16_t crc, cbc;
1492     uint16_t blkA, blkB, blkC, blkD;
1493     uint8_t *fresh, *once, *twice, *display;
1494     uint16_t *event;
1495     uint32_t *flag;
1496
1497     uint8_t rt_addr = 0;
1498     bool txtAB_change = FALSE;  //text AB flag 0 --> 1 or 1-->0 meas new RT incoming 
1499     bool txt_end = FALSE;       //0x0D means text end
1500     bool seg_ok = 0;
1501     static uint16_t bitmap_twice;
1502     static int bitmap_cnt;
1503     int pos = 0;
1504     int rt_len = 0;
1505     int bufsize = 0;
1506     
1507     FM_ASSERT(source);
1508     FM_ASSERT(target);
1509     //source
1510     blkA = source[0];
1511     blkB = source[1];
1512     blkC = source[2];
1513     blkD = source[3];
1514     crc = source[4];
1515     cbc = source[5];
1516     //target
1517     fresh = target->RT_Data.TextData[0];
1518     once = target->RT_Data.TextData[1];
1519     twice = target->RT_Data.TextData[2];
1520     display = target->RT_Data.TextData[3];
1521     event = &target->event_status;
1522     flag = &target->RDSFlag.flag_status;
1523     bufsize = sizeof(target->RT_Data.TextData[0]);
1524
1525     //get basic info: addr, txtAB 
1526     if(rds_group2_rt_addr_get(blkB, &rt_addr))
1527         return ret;
1528     if(rds_group2_txtAB_get(blkB, &target->RDSFlag.Text_AB, &txtAB_change))
1529         return ret;
1530
1531     //RT parsing state machine run
1532     while(1){
1533         switch(rds_rt_state_get()){
1534             case RDS_RT_START:
1535                 if(txtAB_change == TRUE){
1536                     rds_rt_state_set(RDS_RT_DECISION);
1537                     break;
1538                 }else{
1539                     if(rds_group2_rt_get(crc, subtype, blkC, blkD, rt_addr, fresh)){
1540                         rds_rt_state_set(RDS_RT_FINISH); //if CRC error, we should not do parsing
1541                         break;
1542                     }
1543                     rds_group2_rt_cmp(rt_addr, cbc, subtype, fresh, once, twice, 
1544                                 &seg_ok, &txt_end, &rt_len);
1545                     if(seg_ok == TRUE){
1546                         rds_group2_rt_addr_bitmap_set(&bitmap_twice, &bitmap_cnt, rt_addr);
1547                     }
1548                     rds_rt_state_set(RDS_RT_DECISION);
1549                     break;
1550                 }
1551             case RDS_RT_DECISION:
1552                 if(txt_end == TRUE){
1553                     rds_rt_state_set(RDS_RT_GETLEN);  //find 0x0D, and the lenth has been recorded when do rds_group2_rt_cmp()
1554                 }else if(rds_group2_rt_addr_bitmap_get(bitmap_twice) == 0xFFFF //get max  64 chars
1555                         || (txtAB_change == TRUE)  //text AB changed,
1556                         || (bitmap_cnt > RDS_RT_MULTI_REV_TH)){ //repeate many times, but no end char get
1557                     pos = rds_group2_rt_addr_bitmap_get_pos(bitmap_twice);
1558                     rds_group2_rt_get_len(subtype, pos, &rt_len);
1559                     rds_rt_state_set(RDS_RT_GETLEN); 
1560                 }else{
1561                     rds_rt_state_set(RDS_RT_FINISH);
1562                 }
1563                 break;
1564             case RDS_RT_GETLEN:
1565                 memcpy(display, twice, bufsize);
1566                 target->RT_Data.TextLength = rt_len;
1567                 rds_event_set(event, RDS_EVENT_LAST_RADIOTEXT); //yes we got a new RT
1568                 FM_LOG_NTC(D_G2,"Yes, get an RT! [len=%d]\n", rt_len);
1569
1570                 rds_group2_rt_addr_bitmap_clear(&bitmap_twice, &bitmap_cnt);
1571                 //clear buf
1572                 memset(fresh, 0x20, bufsize);
1573                 memset(once, 0x20, bufsize);
1574                 memset(twice, 0x20, bufsize);
1575                 if(txtAB_change == TRUE){
1576                     txtAB_change = FALSE;
1577                     //we need get new RT after show the old RT to the display
1578                     rds_rt_state_set(RDS_RT_START);
1579                 }else{
1580                     rds_rt_state_set(RDS_RT_FINISH);  
1581                 }
1582                 break;
1583             case RDS_RT_FINISH:
1584                 rds_rt_state_set(RDS_RT_START);
1585                 goto out;
1586                 break;
1587             default:
1588                 break;          
1589         }
1590     }
1591 out:
1592     return ret;
1593 }
1594 #endif
1595
1596 static int MT6620_RDS_RetrieveGroup4(uint16_t *block_data, uint8_t SubType, RDSData_Struct *pstRDSData)
1597 {
1598     uint16_t year, month, k=0, D2, minute;
1599     uint32_t MJD, D1;
1600     int ret = 0;
1601         FM_LOG_DBG(D_G4,"RetrieveGroup4 %d\n", SubType);
1602     if(!SubType){
1603         //Type A
1604         if((block_data[4]&FM_RDS_GDBK_IND_C)&&(block_data[4]&FM_RDS_GDBK_IND_D)){            
1605             MJD = (uint32_t) (((block_data[1]&0x0003)<<15) + ((block_data[2]&0xFFFE)>>1));
1606             year = (MJD*100 - 1507820)/36525;
1607                         month = (MJD*10000-149561000-3652500*year)/306001;                      
1608                     if((month == 14)||(month == 15))
1609                     k = 1;              
1610                 D1 = (uint32_t)((36525*year)/100);
1611                 D2 = (uint16_t)((306001*month)/10000);
1612                 pstRDSData->CT.Year = 1900 + year + k;
1613                 pstRDSData->CT.Month = month - 1 - k*12;
1614                 pstRDSData->CT.Day = (uint16_t)(MJD - 14956 - D1 - D2);
1615                 pstRDSData->CT.Hour = ((block_data[2]&0x0001)<<4)+((block_data[3]&0xF000)>>12);
1616                 minute = (block_data[3]&0x0FC0)>>6;
1617
1618                 if(block_data[3]&0x0020){
1619                     pstRDSData->CT.Local_Time_offset_signbit = 1; //0=+, 1=-
1620                 }
1621                 pstRDSData->CT.Local_Time_offset_half_hour = block_data[3]&0x001F;
1622                 if(pstRDSData->CT.Minute != minute){
1623                     pstRDSData->CT.Minute = (block_data[3]&0x0FC0)>>6;
1624                     pstRDSData->event_status |= RDS_EVENT_UTCDATETIME;
1625             }
1626         }
1627     }
1628
1629     return ret;
1630 }
1631
1632 static int MT6620_RDS_RetrieveGroup14(uint16_t *block_data, uint8_t SubType, RDSData_Struct *pstRDSData)
1633 {
1634     uint8_t TP_ON, TA_ON, PI_ON, PS_Num, AF_H, AF_L, indx, indx2, num;
1635     int ret = 0;
1636     FM_LOG_DBG(D_G14,"RetrieveGroup14 %d\n", SubType);
1637         //SubType = (*(block_data+1)&0x0800)>>11;
1638     PI_ON = block_data[3];
1639         TP_ON = block_data[1]&0x0010;                                                   
1640         if((!SubType) && (block_data[4]&FM_RDS_GDBK_IND_C)){
1641             //Type A
1642                 PS_Num= block_data[1]&0x000F;
1643                 if(PS_Num <4){
1644                         for(indx = 0; indx < 2; indx++){
1645                                 pstRDSData->PS_ON[2*PS_Num] = block_data[2]>>8;
1646                                 pstRDSData->PS_ON[2*PS_Num+1] = block_data[2]&0xFF;
1647                         }                                               
1648                 }else if(PS_Num == 4){
1649                         AF_H = (block_data[2]&0xFF00)>>8;
1650                         AF_L = block_data[2]&0x00FF;
1651                         if((AF_H > 223)&&(AF_H < 250)){
1652                             //Followed AF Number
1653                             pstRDSData->AFON_Data.isAFNum_Get = 0;
1654                                 preAFON_Num = AF_H - 224;
1655                                 if(pstRDSData->AFON_Data.AF_Num != preAFON_Num){
1656                                         pstRDSData->AFON_Data.AF_Num = preAFON_Num;
1657                                 }else
1658                                         pstRDSData->AFON_Data.isAFNum_Get= 1;
1659                                         
1660                                 if(AF_L < 205){
1661                                         pstRDSData->AFON_Data.AF[0][0] = AF_L+875;
1662                                         if((pstRDSData->AFON_Data.AF[0][0]) != (pstRDSData->AFON_Data.AF[1][0])){
1663                                                 pstRDSData->AFON_Data.AF[1][0] = pstRDSData->AFON_Data.AF[0][0];
1664                                         }else{
1665                                                 pstRDSData->AFON_Data.isMethod_A = 1;
1666                                         }
1667                                 }
1668                         }else if((pstRDSData->AFON_Data.isAFNum_Get)&&((pstRDSData->AFON_Data.Addr_Cnt) != 0xFF)){
1669                 //AF Num correct
1670                 num = pstRDSData->AFON_Data.AF_Num;
1671                                 num = num>>1;
1672                                 //Put AF freq into buffer and check if AF freq is repeat again
1673                                 for(indx = 1; indx < (num+1); indx++){
1674                                 if((AF_H == (pstRDSData->AFON_Data.AF[0][2*indx-1]))&&(AF_L == (pstRDSData->AFON_Data.AF[0][2*indx]))){
1675                                             FM_LOG_NTC(D_G14,"RetrieveGroup14 AFON same as indx:%d\n", indx);
1676                                                 break;
1677                                         }else if(!(pstRDSData->AFON_Data.AF[0][2*indx-1])){
1678                                             //null buffer
1679                                                 pstRDSData->AFON_Data.AF[0][2*indx-1] = AF_H+875;
1680                                                 pstRDSData->AFON_Data.AF[0][2*indx] = AF_L+875;
1681                                                 break;
1682                                         }
1683                         }
1684                                 num = pstRDSData->AFON_Data.AF_Num;
1685                                 if(num > 0){
1686                                         if((pstRDSData->AFON_Data.AF[0][num-1]) != 0){
1687                                                 num = num>> 1;
1688                                                 //arrange frequency from low to high:start
1689                                                 for(indx = 1; indx < num; indx++){
1690                                                         for(indx2 = indx+1; indx2 < (num+1); indx2++){
1691                                                                 AF_H = pstRDSData->AFON_Data.AF[0][2*indx-1];
1692                                                                 AF_L = pstRDSData->AFON_Data.AF[0][2*indx];
1693                                                                 if(AF_H > (pstRDSData->AFON_Data.AF[0][2*indx2-1])){
1694                                                                         pstRDSData->AFON_Data.AF[0][2*indx-1] = pstRDSData->AFON_Data.AF[0][2*indx2-1];
1695                                                                         pstRDSData->AFON_Data.AF[0][2*indx] = pstRDSData->AFON_Data.AF[0][2*indx2];
1696                                                                         pstRDSData->AFON_Data.AF[0][2*indx2-1] = AF_H;
1697                                                                         pstRDSData->AFON_Data.AF[0][2*indx2] = AF_L;
1698                                                                 }else if(AF_H == (pstRDSData->AFON_Data.AF[0][2*indx2-1])){
1699                                                                         if(AF_L > (pstRDSData->AFON_Data.AF[0][2*indx2])){                      
1700                                                                                 pstRDSData->AFON_Data.AF[0][2*indx-1] = pstRDSData->AFON_Data.AF[0][2*indx2-1];
1701                                                                                 pstRDSData->AFON_Data.AF[0][2*indx] = pstRDSData->AFON_Data.AF[0][2*indx2];
1702                                                                                 pstRDSData->AFON_Data.AF[0][2*indx2-1] = AF_H;
1703                                                                                 pstRDSData->AFON_Data.AF[0][2*indx2] = AF_L;
1704                                                                         }
1705                                             }
1706                                                         }
1707                                                 }
1708                                                 //arrange frequency from low to high:end
1709                                                 //compare AF buff0 and buff1 data:start
1710                                                 num = pstRDSData->AFON_Data.AF_Num;
1711                                                 indx2 = 0;
1712                                                 for(indx = 0; indx < num; indx++){
1713                                                         if((pstRDSData->AFON_Data.AF[1][indx]) == (pstRDSData->AFON_Data.AF[0][indx])){
1714                                                                 if(pstRDSData->AFON_Data.AF[1][indx] != 0)
1715                                                                         indx2++;
1716                                                         }else
1717                                                                 pstRDSData->AFON_Data.AF[1][indx] = pstRDSData->AFON_Data.AF[0][indx];
1718                         }
1719                                                 //compare AF buff0 and buff1 data:end                                           
1720                                                 if(indx2 == num){
1721                                                         pstRDSData->AFON_Data.Addr_Cnt = 0xFF;
1722                             pstRDSData->event_status |= RDS_EVENT_AFON_LIST;                            
1723                                                         for(indx = 0; indx < num; indx++){
1724                                                                 if((pstRDSData->AFON_Data.AF[1][indx]) == 0){
1725                                                                         pstRDSData->AFON_Data.Addr_Cnt = 0x0F;
1726                                                                         pstRDSData->event_status &= (~RDS_EVENT_AFON_LIST);
1727                                                                 }
1728                                                         }
1729                                                 }else
1730                                                         pstRDSData->AFON_Data.Addr_Cnt = 0x0F;
1731                                         }
1732                                 }
1733                         }
1734                 }               
1735         }else{
1736             //Type B
1737             TA_ON = block_data[1]&0x0008;
1738                 FM_LOG_DBG(D_G14,"TA group14 typeB pstRDSData->RDSFlag.TP=%d pstRDSData->RDSFlag.TA=%d TP_ON=%d TA_ON=%d\n", pstRDSData->RDSFlag.TP, pstRDSData->RDSFlag.TA, TP_ON, TA_ON);
1739         if((!pstRDSData->RDSFlag.TP)&&(pstRDSData->RDSFlag.TA)&&TP_ON&&TA_ON){                  
1740                         int TA_num=0;
1741                         for (num=0;num<25;num++){
1742                                 if (pstRDSData->AFON_Data.AF[1][num] != 0){
1743                                         TA_num++;
1744                                 } else {
1745                                         break;
1746                                 }
1747                         }
1748                         FM_LOG_NTC(D_G14,"TA set RDS_EVENT_TAON");
1749                         if (TA_num == pstRDSData->AFON_Data.AF_Num){
1750                             pstRDSData->event_status |= RDS_EVENT_TAON;
1751             }
1752                 }
1753         }
1754
1755     return ret;
1756 }
1757
1758 int MT6620_RDS_OnOff(struct fm *fm, bool bFlag)
1759 {
1760     int ret = 0;
1761     RDSData_Struct *pstRDSData = fm->pstRDSData;
1762     
1763     if(bFlag){
1764         if((ret = MT6620_RDS_Init_Data(pstRDSData)))
1765             return ret;
1766         if((ret = MT6620_RDS_enable()))
1767             return ret;
1768     }else {
1769         if((ret = MT6620_RDS_disable()))
1770             return ret;
1771     }
1772     
1773     return ret;   
1774 }
1775  
1776 /*
1777         Block0:         PI code(16bits)
1778         Block1:         Group type(4bits), B0=version code(1bit), TP=traffic program code(1bit), 
1779                         PTY=program type code(5bits), other(5bits)
1780         Block2: 16bits
1781         Block3: 16bits
1782 */
1783 int MT6620_RDS_Eint_Handler(struct fm *fm, struct rds_rx *rds_raw, int rds_size)
1784 {
1785     int ret = 0;
1786     uint16_t block_data[6];
1787         uint8_t GroupType, SubType = 0;
1788     int rds_cnt = 0;
1789     int i = 0;
1790     bool dirty = FALSE;
1791     //target to fill the result in
1792     RDSData_Struct *pstRDSData = fm->pstRDSData;
1793     uint16_t *event = &pstRDSData->event_status;
1794     uint32_t *flag = &pstRDSData->RDSFlag.flag_status;
1795
1796     ret = rds_cnt_get(rds_raw, rds_size, &rds_cnt);
1797     if(ret){
1798         FM_LOG_WAR(D_RDS,"get cnt err[ret=%d]\n", ret);
1799         return ret;
1800     }
1801         //pstRDSData->EINT_Flag = 1;
1802         while(rds_cnt > 0){
1803         ret = rds_group_get(&block_data[0], rds_raw, i);
1804         if(ret){
1805             FM_LOG_WAR(D_RDS,"get group err[ret=%d]\n", ret);
1806             goto do_next;
1807             }
1808             
1809         ret = rds_group_type_get(block_data[4], block_data[1], &GroupType, &SubType);
1810                 if(ret){
1811             FM_LOG_WAR(D_RDS,"get group type err[ret=%d]\n", ret);
1812             goto do_next; 
1813                         }                       
1814
1815         ret = rds_group_counter_add(GroupType, SubType, &fm->rds_gc);
1816         
1817         ret = rds_group_pi_get(block_data[4], block_data[0], &pstRDSData->PI, &dirty);
1818         if(ret){
1819             FM_LOG_WAR(D_RDS,"get group pi err[ret=%d]\n", ret);
1820             goto do_next;
1821         }else if(dirty == TRUE){
1822             ret = rds_event_set(event, RDS_EVENT_PI_CODE); //yes, we got new PI code
1823                 }
1824                 
1825         ret = rds_group_pty_get(block_data[4], block_data[1], &pstRDSData->PTY, &dirty);
1826         if(ret){
1827             FM_LOG_WAR(D_RDS,"get group pty err[ret=%d]\n", ret);
1828             goto do_next;
1829         }else if(dirty == TRUE){
1830             ret = rds_event_set(event, RDS_EVENT_PTY_CODE); // yes, we got new PTY code
1831                 }
1832                 
1833         ret = rds_group_tp_get(block_data[4], block_data[1], &pstRDSData->RDSFlag.TP, &dirty);
1834         if(ret){
1835             FM_LOG_WAR(D_RDS,"get group tp err[ret=%d]\n", ret);
1836             goto do_next;
1837         }else if(dirty == TRUE){
1838             ret = rds_event_set(event, RDS_EVENT_FLAGS); // yes, we got new TP code
1839             ret = rds_flag_set(flag, RDS_FLAG_IS_TP);
1840                 }
1841                 
1842                 switch(GroupType){
1843                     case 0:
1844                             if((ret = MT6620_RDS_RetrieveGroup0(&block_data[0], SubType, pstRDSData)))
1845                                 goto do_next;
1846                         break;
1847             case 1:
1848                             if((ret = MT6620_RDS_RetrieveGroup1(&block_data[0], SubType, pstRDSData)))
1849                                 goto do_next;
1850                             break;
1851             case 2:
1852                             if((ret = MT6620_RDS_RetrieveGroup2(&block_data[0], SubType, pstRDSData)))  
1853                     goto do_next;
1854                     break;
1855             case 4:
1856                             if((ret = MT6620_RDS_RetrieveGroup4(&block_data[0], SubType, pstRDSData)))
1857                     goto do_next;
1858                             break;              
1859                     case 14:
1860                             if((ret = MT6620_RDS_RetrieveGroup14(&block_data[0], SubType, pstRDSData))) 
1861                     goto do_next;
1862                             break;      
1863             default:
1864                         break;                   
1865                 }
1866
1867 do_next:
1868         if(ret && (ret != -ERR_RDS_CRC)){
1869             FM_LOG_ERR(D_RDS,"parsing err[ret=%d]\n", ret);
1870             return ret;
1871         }
1872         rds_cnt--;
1873         i++;
1874         }
1875
1876     return ret;
1877 }
1878