MT6620: add the new driver JB2 V1.0
[firefly-linux-kernel-4.4.55.git] / drivers / mtk_wcn_combo / drv_fm / core / fm_rds_parser.c
1 /* fm_rds_parser.c
2  *
3  * (C) Copyright 2011
4  * MediaTek <www.MediaTek.com>
5  * hongcheng <hongcheng.xia@MediaTek.com>
6  *
7  * FM Radio Driver
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 #include <linux/string.h>
24
25 #include "fm_typedef.h"
26 #include "fm_rds.h"
27 #include "fm_dbg.h"
28 #include "fm_err.h"
29 #include "fm_stdlib.h"
30
31 //static rds_ps_state_machine_t ps_state_machine = RDS_PS_START;
32 //static rds_rt_state_machine_t rt_state_machine = RDS_RT_START;
33 struct fm_state_machine {
34     fm_s32 state;
35     fm_s32(*state_get)(struct fm_state_machine *thiz);
36     fm_s32(*state_set)(struct fm_state_machine *thiz, fm_s32 new_state);
37 };
38
39 static fm_s32 fm_state_get(struct fm_state_machine *thiz)
40 {
41     return thiz->state;
42 }
43
44 static fm_s32 fm_state_set(struct fm_state_machine *thiz, fm_s32 new_state)
45 {
46     return thiz->state = new_state;
47 }
48
49 #define STATE_SET(a, s)        \
50 {                           \
51     if((a)->state_set){          \
52         (a)->state_set((a), (s));    \
53     }                       \
54 }
55
56 #define STATE_GET(a)         \
57 ({                             \
58     fm_s32 __ret = 0;              \
59     if((a)->state_get){          \
60         __ret = (a)->state_get((a));    \
61     }                       \
62     __ret;                  \
63 })
64
65 static fm_u16(*rds_get_freq)(void)  = NULL;
66
67 //RDS spec related handle flow
68 /*
69  * rds_cnt_get
70  * To get rds group count form raw data
71  * If success return 0, else return error code
72 */
73 static fm_s32 rds_cnt_get(struct rds_rx_t *rds_raw, fm_s32 raw_size, fm_s32 *cnt)
74 {
75     fm_s32 gap = sizeof(rds_raw->cos) + sizeof(rds_raw->sin);
76
77     FMR_ASSERT(rds_raw);
78     FMR_ASSERT(cnt);
79     *cnt = (raw_size - gap) / sizeof(rds_packet_t);
80     WCN_DBG(FM_INF | RDSC, "group cnt=%d\n", *cnt);
81
82     return 0;
83 }
84
85 /*
86  * rds_grp_get
87  * To get rds group[n] data form raw data with index
88  * If success return 0, else return error code
89 */
90 static fm_s32 rds_grp_get(fm_u16 *dst, struct rds_rx_t *raw, fm_s32 idx)
91 {
92     FMR_ASSERT(dst);
93     FMR_ASSERT(raw);
94
95     if (idx > (MAX_RDS_RX_GROUP_CNT - 1)) {
96         return -FM_EPARA;
97     }
98
99     dst[0] = raw->data[idx].blkA;
100     dst[1] = raw->data[idx].blkB;
101     dst[2] = raw->data[idx].blkC;
102     dst[3] = raw->data[idx].blkD;
103     dst[4] = raw->data[idx].crc;
104     dst[5] = raw->data[idx].cbc;
105
106     WCN_DBG(FM_NTC | RDSC, "BLOCK:%04x %04x %04x %04x, CRC:%04x CBC:%04x\n", dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
107
108     return 0;
109 }
110
111 /*
112  * rds_checksum_check
113  * To check CRC rerult, if OK, *valid=fm_true, else *valid=fm_false
114  * If success return 0, else return error code
115 */
116 static fm_s32 rds_checksum_check(fm_u16 crc, fm_s32 mask, fm_bool *valid)
117 {
118     FMR_ASSERT(valid);
119
120     if ((crc & mask) == mask) {
121         *valid = fm_true;
122     } else {
123         *valid = fm_false;
124     }
125
126     return 0;
127 }
128
129 /*
130  * rds_cbc_get - To get block_n's correct bit count form cbc
131  * @cbc, the group's correct bit count
132  * @blk, target the block
133  *
134  * If success, return block_n's cbc, else error code
135 */
136 /*
137 static fm_s32 rds_cbc_get(fm_u16 cbc, enum rds_blk_t blk)
138 {
139     int ret = 0;
140
141     switch (blk) {
142     case RDS_BLK_A:
143         ret = (cbc & 0xF000) >> 12;
144         break;
145     case RDS_BLK_B:
146         ret = (cbc & 0x0F00) >> 8;
147         break;
148     case RDS_BLK_C:
149         ret = (cbc & 0x00F0) >> 4;
150         break;
151     case RDS_BLK_D:
152         ret = (cbc & 0x000F) >> 0;
153         break;
154     default:
155         break;
156     }
157
158     WCN_DBG(FM_INF | RDSC, "group cbc=0x%04x\n", cbc);
159     return ret;
160 }
161 */
162 /*
163  * rds_event_set
164  * To set rds event, and user space can use this flag to juge which event happened
165  * If success return 0, else return error code
166 */
167 static fm_s32 rds_event_set(fm_u16 *events, fm_s32 event_mask)
168 {
169     FMR_ASSERT(events);
170         WCN_DBG(FM_NTC | RDSC, "rds set event[%x->%x]\n", event_mask,*events);
171     *events |= event_mask;
172
173     return 0;
174 }
175
176 /*
177  * rds_flag_set
178  * To set rds event flag, and user space can use this flag to juge which event happened
179  * If success return 0, else return error code
180 */
181 static fm_s32 rds_flag_set(fm_u32 *flags, fm_s32 flag_mask)
182 {
183     FMR_ASSERT(flags);
184     *flags |= flag_mask;
185         WCN_DBG(FM_NTC | RDSC, "rds set flag[%x->%x]\n", flag_mask,*flags);
186
187     return 0;
188 }
189
190 /*
191  * rds_grp_type_get
192  * To get rds group type form blockB
193  * If success return 0, else return error code
194 */
195 static fm_s32 rds_grp_type_get(fm_u16 crc, fm_u16 blk, fm_u8 *type, fm_u8 *subtype)
196 {
197     fm_bool valid = fm_false;
198
199     FMR_ASSERT(type);
200     FMR_ASSERT(subtype);
201     //to get the group type from block B
202     rds_checksum_check(crc, FM_RDS_GDBK_IND_B, &valid);
203
204     if (valid == fm_true) {
205         *type = (blk & 0xF000) >> 12; //Group type(4bits)
206         *subtype = (blk & 0x0800) >> 11; //version code(1bit), 0=vesionA, 1=versionB
207     } else {
208         WCN_DBG(FM_WAR | RDSC, "Block1 CRC err\n");
209         return -FM_ECRC;
210     }
211
212     WCN_DBG(FM_DBG | RDSC, "Type=%d, subtype:%s\n", (fm_s32)*type, *subtype ? "version B" : "version A");
213     return 0;
214 }
215
216 /*
217  * rds_grp_counter_add
218  * @type -- group type, rang: 0~15
219  * @subtype -- sub group type, rang:0~1
220  *
221  * add group counter, g0a~g15b
222  * we use type value as the index
223  * If success return 0, else return error code
224 */
225 static fm_s32 rds_grp_counter_add(fm_u8 type, fm_u8 subtype, struct rds_group_cnt_t *gc)
226 {
227     FMR_ASSERT(gc);
228
229     if (type > 15) {
230         return -FM_EPARA;
231     }
232
233     switch (subtype) {
234     case RDS_GRP_VER_A:
235         gc->groupA[type]++;
236         break;
237     case RDS_GRP_VER_B:
238         gc->groupB[type]++;
239         break;
240     default:
241         return -FM_EPARA;
242         break;
243     }
244
245     gc->total++;
246     WCN_DBG(FM_INF | RDSC, "group counter:%d\n", (fm_s32)gc->total);
247     return 0;
248 }
249
250 /*
251  * rds_grp_counter_get
252  *
253  * read group counter , g0a~g15b
254  * If success return 0, else return error code
255 */
256 extern fm_s32 rds_grp_counter_get(struct rds_group_cnt_t *dst, struct rds_group_cnt_t *src)
257 {
258     FMR_ASSERT(dst);
259     FMR_ASSERT(src);
260     fm_memcpy(dst, src, sizeof(struct rds_group_cnt_t));
261     WCN_DBG(FM_DBG | RDSC, "rds gc get[total=%d]\n", (fm_s32)dst->total);
262     return 0;
263 }
264
265 /*
266  * rds_grp_counter_reset
267  *
268  * clear group counter to 0, g0a~g15b
269  * If success return 0, else return error code
270 */
271 extern fm_s32 rds_grp_counter_reset(struct rds_group_cnt_t *gc)
272 {
273     FMR_ASSERT(gc);
274     fm_memset(gc, 0, sizeof(struct rds_group_cnt_t));
275     return 0;
276 }
277
278 extern fm_s32 rds_log_in(struct rds_log_t *thiz, struct rds_rx_t *new_log, fm_s32 new_len)
279 {
280     FMR_ASSERT(new_log);
281
282     if (thiz->len < thiz->size) {
283         new_len = (new_len < sizeof(struct rds_rx_t)) ? new_len : sizeof(struct rds_rx_t);
284         fm_memcpy(&(thiz->rds_log[thiz->in]), new_log, new_len);
285         thiz->log_len[thiz->in] = new_len;
286         thiz->in = (thiz->in + 1) % thiz->size;
287         thiz->len++;
288         WCN_DBG(FM_DBG | RDSC, "add a new log[len=%d]\n", thiz->len);
289     } else {
290         WCN_DBG(FM_WAR | RDSC, "rds log buf is full\n");
291         return -FM_ENOMEM;
292     }
293
294     return 0;
295 }
296
297 extern fm_s32 rds_log_out(struct rds_log_t *thiz, struct rds_rx_t *dst, fm_s32 *dst_len)
298 {
299     FMR_ASSERT(dst);
300     FMR_ASSERT(dst_len);
301
302     if (thiz->len > 0) {
303         *dst_len = thiz->log_len[thiz->out];
304         *dst_len = (*dst_len < sizeof(struct rds_rx_t)) ? *dst_len : sizeof(struct rds_rx_t);
305         fm_memcpy(dst, &(thiz->rds_log[thiz->out]), *dst_len);
306         thiz->out = (thiz->out + 1) % thiz->size;
307         thiz->len--;
308         WCN_DBG(FM_DBG | RDSC, "del a new log[len=%d]\n", thiz->len);
309     } else {
310         *dst_len = 0;
311         WCN_DBG(FM_WAR | RDSC, "rds log buf is empty\n");
312     }
313
314     return 0;
315 }
316
317 /*
318  * rds_grp_pi_get
319  * To get rds group pi code form blockA
320  * If success return 0, else return error code
321 */
322 static fm_s32 rds_grp_pi_get(fm_u16 crc, fm_u16 blk, fm_u16 *pi, fm_bool *dirty)
323 {
324     fm_s32 ret = 0;
325     fm_bool valid = fm_false;
326
327     FMR_ASSERT(pi);
328     FMR_ASSERT(dirty);
329
330     //to get the group pi code from block A
331     ret = rds_checksum_check(crc, FM_RDS_GDBK_IND_A, &valid);
332
333     if (valid == fm_true) {
334         if (*pi != blk) {
335             //PI=program Identication
336             *pi = blk;
337             *dirty = fm_true; // yes, we got new PI code
338         } else {
339             *dirty = fm_false; // PI is the same as last one
340         }
341     } else {
342         WCN_DBG(FM_WAR | RDSC, "Block0 CRC err\n");
343         return -FM_ECRC;
344     }
345
346     WCN_DBG(FM_INF | RDSC, "PI=0x%04x, %s\n", *pi, *dirty ? "new" : "old");
347     return ret;
348 }
349
350 /*
351  * rds_grp_pty_get
352  * To get rds group pty code form blockB
353  * If success return 0, else return error code
354 */
355 static fm_s32 rds_grp_pty_get(fm_u16 crc, fm_u16 blk, fm_u8 *pty, fm_bool *dirty)
356 {
357     fm_s32 ret = 0;
358 //    fm_bool valid = fm_false;
359
360     FMR_ASSERT(pty);
361     FMR_ASSERT(dirty);
362
363     //to get PTY code from block B
364 //    ret = rds_checksum_check(crc, FM_RDS_GDBK_IND_B, &valid);
365
366 //    if (valid == fm_false) {
367 //        WCN_DBG(FM_WAR | RDSC, "Block1 CRC err\n");
368 //        return -FM_ECRC;
369 //    }
370
371     if (*pty != ((blk & 0x03E0) >> 5)) {
372         //PTY=Program Type Code
373         *pty = (blk & 0x03E0) >> 5;
374         *dirty = fm_true; // yes, we got new PTY code
375     } else {
376         *dirty = fm_false; // PTY is the same as last one
377     }
378
379     WCN_DBG(FM_INF | RDSC, "PTY=%d, %s\n", (fm_s32)*pty, *dirty ? "new" : "old");
380     return ret;
381 }
382
383 /*
384  * rds_grp_tp_get
385  * To get rds group tp code form blockB
386  * If success return 0, else return error code
387 */
388 static fm_s32 rds_grp_tp_get(fm_u16 crc, fm_u16 blk, fm_u8 *tp, fm_bool *dirty)
389 {
390     fm_s32 ret = 0;
391 //    fm_bool valid = fm_false;
392
393     FMR_ASSERT(tp);
394     FMR_ASSERT(dirty);
395
396     //to get TP code from block B
397 //    ret = rds_checksum_check(crc, FM_RDS_GDBK_IND_B, &valid);
398
399 //    if (valid == fm_false) {
400 //        WCN_DBG(FM_WAR | RDSC, "Block1 CRC err\n");
401 //        return -FM_ECRC;
402 //    }
403
404     if (*tp != ((blk&0x0400) >> 10)) {
405         //Tranfic Program Identification
406         *tp = (blk & 0x0400) >> 10;
407         *dirty = fm_true; // yes, we got new TP code
408     } else {
409         *dirty = fm_false; // TP is the same as last one
410     }
411
412     WCN_DBG(FM_NTC | RDSC, "TP=%d, %s\n", (fm_s32)*tp, *dirty ? "new" : "old");
413     return ret;
414 }
415
416 /*
417  * rds_g0_ta_get
418  * To get rds group ta code form blockB
419  * If success return 0, else return error code
420 */
421 static fm_s32 rds_g0_ta_get(fm_u16 blk, fm_u8 *ta, fm_bool *dirty)
422 {
423     fm_s32 ret = 0;
424
425     FMR_ASSERT(ta);
426     FMR_ASSERT(dirty);
427
428     //TA=Traffic Announcement code
429     if (*ta != ((blk & 0x0010) >> 4)) {
430         *ta = (blk & 0x0010) >> 4;
431         *dirty = fm_true; // yes, we got new TA code
432     } else {
433         *dirty = fm_false; // TA is the same as last one
434     }
435
436     WCN_DBG(FM_INF | RDSC, "TA=%d, %s\n", (fm_s32)*ta, *dirty ? "new" : "old");
437     return ret;
438 }
439
440 /*
441  * rds_g0_music_get
442  * To get music-speech switch code form blockB
443  * If success return 0, else return error code
444 */
445 static fm_s32 rds_g0_music_get(fm_u16 blk, fm_u8 *music, fm_bool *dirty)
446 {
447     fm_s32 ret = 0;
448
449     FMR_ASSERT(music);
450     FMR_ASSERT(dirty);
451
452     //M/S=music speech switch code
453     if (*music != ((blk & 0x0008) >> 3)) {
454         *music = (blk & 0x0008) >> 3;
455         *dirty = fm_true; // yes, we got new music code
456     } else {
457         *dirty = fm_false; // music  is the same as last one
458     }
459
460     WCN_DBG(FM_INF | RDSC, "Music=%d, %s\n", (fm_s32)*music, *dirty ? "new" : "old");
461     return ret;
462 }
463
464 /*
465  * rds_g0_ps_addr_get
466  * To get ps addr form blockB, blkB b0~b1
467  * If success return 0, else return error code
468 */
469 static fm_s32 rds_g0_ps_addr_get(fm_u16 blkB, fm_u8 *addr)
470 {
471     FMR_ASSERT(addr);
472     *addr = (fm_u8)blkB & 0x03;
473
474     WCN_DBG(FM_INF | RDSC, "addr=0x%02x\n", *addr);
475     return 0;
476 }
477
478 /*
479  * rds_g0_di_flag_get
480  * To get DI segment flag form blockB, blkB b2
481  * If success return 0, else return error code
482 */
483 static fm_s32 rds_g0_di_flag_get(fm_u16 blkB, fm_u8 *flag)
484 {
485     FMR_ASSERT(flag);
486     *flag = (fm_u8)((blkB & 0x0004) >> 2);
487
488     WCN_DBG(FM_INF | RDSC, "flag=0x%02x\n", *flag);
489     return 0;
490 }
491
492 static fm_s32 rds_g0_ps_get(fm_u16 crc, fm_u16 blkD, fm_u8 addr, fm_u8 *buf)
493 {
494 //    fm_bool valid = fm_false;
495     fm_s32 idx = 0;
496
497     FMR_ASSERT(buf);
498
499     //ps segment addr rang 0~3
500     if (addr > 0x03) {
501         WCN_DBG(FM_ERR | RDSC, "addr invalid(0x%02x)\n", addr);
502         return -FM_EPARA;
503     } else {
504         idx = 2 * addr;
505     }
506
507         buf[idx] = blkD >> 8;
508         buf[idx+1] = blkD & 0xFF;
509         #if 0
510     rds_checksum_check(crc, FM_RDS_GDBK_IND_D, &valid);
511
512     if (valid == fm_true) {
513         buf[idx] = blkD >> 8;
514         buf[idx+1] = blkD & 0xFF;
515     } else {
516         WCN_DBG(FM_ERR | RDSC, "ps crc check err\n");
517         return -FM_ECRC;
518     }
519     #endif
520
521     WCN_DBG(FM_NTC | RDSC, "PS:addr[%02x]:0x%02x 0x%02x\n", addr, buf[idx], buf[idx+1]);
522     return 0;
523 }
524
525 /*
526  * rds_g0_ps_cmp
527  * this function is the most importent flow for PS parsing
528  * 1.Compare fresh buf with once buf per byte, if eque copy this byte to twice buf, else copy it to once buf
529  * 2.Check wether we got a full segment
530  * If success return 0, else return error code
531 */
532 static fm_s32 rds_g0_ps_cmp(fm_u8 addr, fm_u16 cbc, fm_u8 *fresh,
533                             fm_u8 *once, fm_u8 *twice, /*fm_bool *valid,*/fm_u8 *bm)
534 {
535         fm_s32 ret = 0,indx;
536         //    fm_s32 i = 0;
537         //fm_s32 j = 0;
538         //    fm_s32 cnt = 0;
539         fm_u8 AF_H, AF_L,PS_Num;
540         //fm_u8 corrBitCnt_BlkB, corrBitCnt_BlkD;
541         static fm_s8 Pre_PS_Num = -1;
542
543         FMR_ASSERT(fresh);
544         FMR_ASSERT(once);
545         FMR_ASSERT(twice);
546 //      FMR_ASSERT(valid);
547
548         //j = 2; // PS segment width
549         PS_Num = addr;
550         //corrBitCnt_BlkB = rds_cbc_get(cbc, RDS_BLK_B);
551         //corrBitCnt_BlkD = rds_cbc_get(cbc, RDS_BLK_D);
552
553         AF_H = once[2*PS_Num];
554         AF_L = once[2*PS_Num+1];
555         if((AF_H == fresh[2*PS_Num])&&(AF_L == fresh[2*PS_Num+1]))
556         {
557                 twice[2*PS_Num] = once[2*PS_Num];
558                 twice[2*PS_Num+1] = once[2*PS_Num+1];
559                 *bm |= 1<<PS_Num;
560         }
561         else
562         {
563                 if (PS_Num-Pre_PS_Num > 1) 
564                 {
565                         for (indx=Pre_PS_Num+1; indx<PS_Num; indx++) 
566                         {
567                                 *bm &= ~(1<<indx);
568                                 once[2*indx] = 0x00;
569                                 once[2*indx+1] = 0x00;
570                                 twice[2*indx] = 0x00;
571                                 twice[2*indx+1] = 0x00;
572                         }
573                 }
574                 else if (PS_Num-Pre_PS_Num < 1) 
575                 {
576                         for (indx=0; indx<PS_Num; indx++) 
577                         {
578                                 *bm &= ~(1<<indx);
579                                 once[2*indx] = 0x00;
580                                 once[2*indx+1] = 0x00;
581                                 twice[2*indx] = 0x00;
582                                 twice[2*indx+1] = 0x00;
583                         }
584                 }
585                 
586                 if ((once[2*PS_Num] != 0) || (once[2*PS_Num+1] != 0)) 
587                 {
588                         for (indx=PS_Num; indx<4; indx++) 
589                         {
590                                 *bm &= ~(1<<indx);
591                         }
592                 }
593                 //if((corrBitCnt_BlkB == 0) && (corrBitCnt_BlkD == 0)) 
594                 if(cbc==0)
595         {
596                         *bm |= 1<<PS_Num;       
597                         once[2*PS_Num]=fresh[2*PS_Num];
598                         once[2*PS_Num+1] = fresh[2*PS_Num+1];
599                         twice[2*PS_Num]=fresh[2*PS_Num];
600                         twice[2*PS_Num+1] = fresh[2*PS_Num+1];
601                 } 
602                 else 
603                 {
604                         once[2*PS_Num]=fresh[2*PS_Num];
605                         once[2*PS_Num+1] = fresh[2*PS_Num+1];
606                 }
607         }
608         
609         Pre_PS_Num = PS_Num;
610 #if     0
611         if (rds_cbc_get(cbc, RDS_BLK_D) == 0) {
612             once[j*addr] = fresh[j*addr];
613             once[j*addr+1] = fresh[j*addr+1];
614         }
615         if((once[j*addr] == fresh[j*addr])&&(once[j*addr+1] == fresh[j*addr+1]))
616         {
617                 twice[j*addr] = once[j*addr];
618                 twice[j*addr+1] = once[j*addr+1];
619                 *valid = fm_true;
620         }
621         else
622         {
623                 once[j*addr] = fresh[j*addr];
624                 once[j*addr+1] = fresh[j*addr+1];
625                 *valid = fm_false;
626         }
627 #endif
628 #if     0
629     for (i = 0; i < j; i++) {
630         if (fresh[j*addr+i] == once[j*addr+i]) {
631             twice[j*addr+i] = once[j*addr+i]; //get the same byte 2 times
632             cnt++;
633         } else {
634             once[j*addr+i] = fresh[j*addr+i]; //use new val
635         }
636     }
637
638     //check if we got a valid segment
639     if (cnt == j) {
640         *valid = fm_true;
641     } else {
642         *valid = fm_false;
643     }
644 #endif
645     //WCN_DBG(FM_NTC | RDSC, "PS seg=%s\n", *valid == fm_true ? "fm_true" : "fm_false");
646     WCN_DBG(FM_NTC | RDSC, "bitmap=%x\n", *bm);
647     WCN_DBG(FM_NTC | RDSC, "PS[1]=%x %x %x %x %x %x %x %x\n", once[0],once[1],once[2],once[3],once[4],once[5],once[6],once[7]);
648     WCN_DBG(FM_NTC | RDSC, "PS[2]=%x %x %x %x %x %x %x %x\n", twice[0],twice[1],twice[2],twice[3],twice[4],twice[5],twice[6],twice[7]);
649     return ret;
650 }
651
652 struct rds_bitmap {
653     fm_u16 bm;
654     fm_s32 cnt;
655     fm_s32 max_addr;
656     fm_u16(*bm_get)(struct rds_bitmap *thiz);
657     fm_s32(*bm_cnt_get)(struct rds_bitmap *thiz);
658     fm_s32(*bm_get_pos)(struct rds_bitmap *thiz);
659     fm_s32(*bm_clr)(struct rds_bitmap *thiz);
660     fm_s32(*bm_cmp)(struct rds_bitmap *thiz, struct rds_bitmap *that);
661     fm_s32(*bm_set)(struct rds_bitmap *thiz, fm_u8 addr);
662 };
663
664 static fm_u16 rds_bm_get(struct rds_bitmap *thiz)
665 {
666     return thiz->bm;
667 }
668
669 static fm_s32 rds_bm_cnt_get(struct rds_bitmap *thiz)
670 {
671     return thiz->cnt;
672 }
673
674 #define FM_RDS_USE_SOLUTION_B
675
676 static fm_s32 rds_bm_get_pos(struct rds_bitmap *thiz)
677 {
678     fm_s32 i = thiz->max_addr;
679     fm_s32 j;
680
681     j = 0;
682
683     while (!(thiz->bm & (1 << i)) && (i > -1)) {
684         i--;
685     }
686
687 #ifdef FM_RDS_USE_SOLUTION_B
688     for (j = i; j >= 0; j--) {
689         if (!(thiz->bm & (1 << j))) {
690             WCN_DBG(FM_NTC | RDSC, "uncomplete msg 0x%04x, delete it\n", thiz->bm);
691             return -1;
692         }
693     }
694 #endif
695
696     return i;
697 }
698
699 static fm_s32 rds_bm_clr(struct rds_bitmap *thiz)
700 {
701     thiz->bm = 0x0000;
702     thiz->cnt = 0;
703     return 0;
704 }
705
706 static fm_s32 rds_bm_cmp(struct rds_bitmap *bitmap1, struct rds_bitmap *bitmap2)
707 {
708     return (fm_s32)(bitmap1->bm - bitmap2->bm);
709 }
710
711 static fm_s32 rds_bm_set(struct rds_bitmap *thiz, fm_u8 addr)
712 {
713     struct rds_bitmap bm_old;
714
715     //text segment addr rang
716     if (addr > thiz->max_addr) {
717         WCN_DBG(FM_ERR | RDSC, "addr invalid(0x%02x)\n", addr);
718         return -FM_EPARA;
719     }
720
721     bm_old.bm = thiz->bm;
722     thiz->bm |= (1 << addr); //set bitmap
723
724     if (!rds_bm_cmp(&bm_old, thiz)) {
725         thiz->cnt++;  // multi get a segment
726     } else if (thiz->cnt > 0) {
727         thiz->cnt--;
728     }
729
730     return 0;
731 }
732
733
734 /*
735  * rds_g2_rt_addr_get
736  * To get rt addr form blockB
737  * If success return 0, else return error code
738 */
739 static fm_s32 rds_g2_rt_addr_get(fm_u16 blkB, fm_u8 *addr)
740 {
741     fm_s32 ret = 0;
742
743     FMR_ASSERT(addr);
744     *addr = (fm_u8)blkB & 0x0F;
745
746     WCN_DBG(FM_INF | RDSC, "addr=0x%02x\n", *addr);
747     return ret;
748 }
749
750 static fm_s32 rds_g2_txtAB_get(fm_u16 blk, fm_u8 *txtAB, fm_bool *dirty)
751 {
752     fm_s32 ret = 0;
753
754     FMR_ASSERT(txtAB);
755     FMR_ASSERT(dirty);
756
757         if (*txtAB != ((blk&0x0010) >> 4)) 
758         {
759                 *txtAB = (blk & 0x0010) >> 4;
760                 *dirty = fm_true; // yes, we got new txtAB code
761                 WCN_DBG(FM_INF | RDSC, "changed! txtAB=%d\n", *txtAB);
762     } else {
763         *dirty = fm_false; // txtAB is the same as last one
764     }
765
766     WCN_DBG(FM_INF | RDSC, "txtAB=%d, %s\n", *txtAB, *dirty ? "new" : "old");
767     return ret;
768 }
769
770 static fm_s32 rds_g2_rt_get(fm_u16 crc, fm_u8 subtype, fm_u16 blkC, fm_u16 blkD, fm_u8 addr, fm_u8 *buf)
771 {
772     fm_s32 ret = 0;
773     fm_bool valid = fm_false;
774     fm_s32 idx = 0;
775
776     FMR_ASSERT(buf);
777
778     //text segment addr rang 0~15
779     if (addr > 0x0F) {
780         WCN_DBG(FM_ERR | RDSC, "addr invalid(0x%02x)\n", addr);
781         ret = -FM_EPARA;
782         return ret;
783     }
784
785     switch (subtype) {
786     case RDS_GRP_VER_A:
787         idx = 4 * addr;
788         ret = rds_checksum_check(crc, FM_RDS_GDBK_IND_C | FM_RDS_GDBK_IND_D, &valid);
789
790         if (valid == fm_true) {
791             buf[idx] = blkC >> 8;
792             buf[idx+1] = blkC & 0xFF;
793             buf[idx+2] = blkD >> 8;
794             buf[idx+3] = blkD & 0xFF;
795         } else {
796             WCN_DBG(FM_ERR | RDSC, "rt crc check err\n");
797             ret = -FM_ECRC;
798         }
799
800         break;
801     case RDS_GRP_VER_B:
802         idx = 2 * addr;
803         ret = rds_checksum_check(crc, FM_RDS_GDBK_IND_D, &valid);
804
805         if (valid == fm_true) {
806             buf[idx] = blkD >> 8;
807             buf[idx+1] = blkD & 0xFF;
808         } else {
809             WCN_DBG(FM_ERR | RDSC, "rt crc check err\n");
810             ret = -FM_ECRC;
811         }
812
813         break;
814     default:
815         break;
816     }
817
818     WCN_DBG(FM_NTC | RDSC, "fresh addr[%02x]:0x%02x%02x 0x%02x%02x\n", addr, buf[idx], buf[idx+1], buf[idx+2], buf[idx+3]);
819     return ret;
820 }
821
822 static fm_s32 rds_g2_rt_get_len(fm_u8 subtype, fm_s32 pos, fm_s32 *len)
823 {
824     fm_s32 ret = 0;
825
826     FMR_ASSERT(len);
827
828     if (subtype == RDS_GRP_VER_A) {
829         *len = 4 * (pos + 1);
830     } else {
831         *len = 2 * (pos + 1);
832     }
833
834     return ret;
835 }
836
837 /*
838  * rds_g2_rt_cmp
839  * this function is the most importent flow for RT parsing
840  * 1.Compare fresh buf with once buf per byte, if eque copy this byte to twice buf, else copy it to once buf
841  * 2.Check wether we got a full segment, for typeA if copyed 4bytes to twice buf, for typeB 2bytes copyed to twice buf
842  * 3.Check wether we got the end of RT, if we got 0x0D
843  * 4.If we got the end, then caculate the RT lenth
844  * If success return 0, else return error code
845 */
846 static fm_s32 rds_g2_rt_cmp(fm_u8 addr, fm_u16 cbc, fm_u8 subtype, fm_u8 *fresh,
847                             fm_u8 *once, fm_u8 *twice, fm_bool *valid/*, fm_bool *end, fm_s32 *len*/)
848 {
849     fm_s32 ret = 0;
850     fm_s32 i = 0;
851     fm_s32 j = 0;
852     fm_s32 cnt = 0;
853
854     FMR_ASSERT(fresh);
855     FMR_ASSERT(once);
856     FMR_ASSERT(twice);
857     FMR_ASSERT(valid);
858 //    FMR_ASSERT(end);
859
860     j = (subtype == RDS_GRP_VER_A) ? 4 : 2; // RT segment width
861
862     if (subtype == RDS_GRP_VER_A) {
863         //if (rds_cbc_get(cbc, RDS_BLK_C) == 0) 
864         if(cbc==0)
865         {
866             once[j*addr+0] = fresh[j*addr+0];
867             once[j*addr+1] = fresh[j*addr+1];
868         //}
869
870         //if (rds_cbc_get(cbc, RDS_BLK_D) == 0) 
871        // {
872             once[j*addr+2] = fresh[j*addr+2];
873             once[j*addr+3] = fresh[j*addr+3];
874         }
875     } else if (subtype == RDS_GRP_VER_B) {
876         //if (rds_cbc_get(cbc, RDS_BLK_D) == 0)
877                 if(cbc==0)
878         {
879             once[j*addr+0] = fresh[j*addr+0];
880             once[j*addr+1] = fresh[j*addr+1];
881         }
882     }
883
884     for (i = 0; i < j; i++) {
885         if (fresh[j*addr+i] == once[j*addr+i]) {
886             twice[j*addr+i] = once[j*addr+i]; //get the same byte 2 times
887             cnt++;
888                         WCN_DBG(FM_NTC | RDSC, "twice=%d\n", j*addr+i);
889         } else {
890             once[j*addr+i] = fresh[j*addr+i]; //use new val
891                         WCN_DBG(FM_NTC | RDSC, "once=%d\n", j*addr+i);
892         }
893 #if 0
894         //if we got 0x0D twice, it means a RT end
895         if (twice[j*addr+i] == 0x0D) {
896             *end = fm_true;
897             *len = j * addr + i + 1; //record the length of RT
898                         WCN_DBG(FM_NTC | RDSC, "get 0D=%d\n", *len);
899         }
900 #endif        
901     }
902
903     //check if we got a valid segment 4bytes for typeA, 2bytes for typeB
904     if (cnt == j) {
905         *valid = fm_true;
906     } else {
907         *valid = fm_false;
908     }
909
910     WCN_DBG(FM_INF | RDSC, "RT seg=%s\n", *valid == fm_true ? "fm_true" : "fm_false");
911 //    WCN_DBG(FM_INF | RDSC, "RT end=%s\n", *end == fm_true ? "fm_true" : "fm_false");
912 //    WCN_DBG(FM_INF | RDSC, "RT len=%d\n", *len);
913     return ret;
914 }
915
916 /*
917  * rds_g2_rt_check_end
918  * check 0x0D end flag
919  * If we got the end, then caculate the RT lenth
920  * If success return 0, else return error code
921 */
922 static fm_s32 rds_g2_rt_check_end(fm_u8 addr, fm_u8 subtype, fm_u8 *twice,fm_bool *end)
923 {
924     fm_s32 i = 0;
925     fm_s32 j = 0;
926
927     FMR_ASSERT(twice);
928     FMR_ASSERT(end);
929
930     j = (subtype == RDS_GRP_VER_A) ? 4 : 2; // RT segment width
931         *end = fm_false;
932
933     for (i = 0; i < j; i++) 
934     {
935         //if we got 0x0D twice, it means a RT end
936         if (twice[j*addr+i] == 0x0D) 
937         {
938             *end = fm_true;
939                         WCN_DBG(FM_NTC | RDSC, "get 0x0D\n");
940                         break;
941         }
942     }
943
944     return 0;
945 }
946
947 static fm_s32 rds_retrieve_g0_af(fm_u16 *block_data, fm_u8 SubType, rds_t *pstRDSData)
948 {
949     static fm_s16 preAF_Num = 0;
950     fm_u8 indx, indx2, AF_H, AF_L, num;
951     fm_s32 ret = 0;
952     fm_bool valid = fm_false;
953     fm_bool dirty = fm_false;
954     fm_u16 *event = &pstRDSData->event_status;
955     fm_u32 *flag = &pstRDSData->RDSFlag.flag_status;
956
957 //    ret = rds_checksum_check(block_data[4], FM_RDS_GDBK_IND_D, &valid);
958
959 //    if (valid == fm_false) {
960 //        WCN_DBG(FM_WAR | RDSC, "Group0 BlockD crc err\n");
961 //        return -FM_ECRC;
962 //    }
963
964     ret = rds_g0_ta_get(block_data[1], &pstRDSData->RDSFlag.TA, &dirty);
965
966     if (ret) {
967         WCN_DBG(FM_WAR | RDSC, "get ta failed[ret=%d]\n", ret);
968     } else if (dirty == fm_true) {
969         ret = rds_event_set(event, RDS_EVENT_FLAGS); // yes, we got new TA code
970         ret = rds_flag_set(flag, RDS_FLAG_IS_TA);
971     }
972
973     ret = rds_g0_music_get(block_data[1], &pstRDSData->RDSFlag.Music, &dirty);
974
975     if (ret) {
976         WCN_DBG(FM_WAR | RDSC, "get music failed[ret=%d]\n", ret);
977     } else if (dirty == fm_true) {
978         ret = rds_event_set(event, RDS_EVENT_FLAGS); // yes, we got new MUSIC code
979         ret = rds_flag_set(flag, RDS_FLAG_IS_MUSIC);
980     }
981
982     if ((pstRDSData->Switch_TP) && (pstRDSData->RDSFlag.TP) && !(pstRDSData->RDSFlag.TA)) {
983         ret = rds_event_set(event, RDS_EVENT_TAON_OFF);
984     }
985
986     if (!SubType) {
987         //Type A
988         ret = rds_checksum_check(block_data[4], FM_RDS_GDBK_IND_C, &valid);
989
990         if (valid == fm_false) {
991             WCN_DBG(FM_WAR | RDSC, "Group0 BlockC crc err\n");
992             return -FM_ECRC;
993         } else {
994             AF_H = (block_data[2] & 0xFF00) >> 8;
995             AF_L = block_data[2] & 0x00FF;
996
997             if ((AF_H > 224) && (AF_H < 250)) {
998                 //Followed AF Number, see RDS spec Table 11, valid(224-249)
999                 WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 AF_H:%d, AF_L:%d\n", AF_H, AF_L);
1000                 preAF_Num = AF_H - 224; //AF Number
1001
1002                 if (preAF_Num != pstRDSData->AF_Data.AF_Num) {
1003                     pstRDSData->AF_Data.AF_Num = preAF_Num;
1004                                         pstRDSData->AF_Data.isAFNum_Get = 0;
1005                 } else {
1006                     //Get the same AFNum two times
1007                     pstRDSData->AF_Data.isAFNum_Get = 1;
1008                 }
1009
1010                 if ((AF_L < 205) && (AF_L > 0)) {
1011                     //See RDS Spec table 10, valid VHF
1012                     pstRDSData->AF_Data.AF[0][0] = AF_L + 875; //convert to 100KHz
1013 #ifdef MTK_FM_50KHZ_SUPPORT
1014                     pstRDSData->AF_Data.AF[0][0] *= 10;
1015 #endif
1016                     WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 AF[0][0]:%d\n", pstRDSData->AF_Data.AF[0][0]);
1017
1018                     if ((pstRDSData->AF_Data.AF[0][0]) != (pstRDSData->AF_Data.AF[1][0])) {
1019                         pstRDSData->AF_Data.AF[1][0] = pstRDSData->AF_Data.AF[0][0];
1020                     } else {
1021                         if (pstRDSData->AF_Data.AF[1][0] !=  rds_get_freq())
1022                             pstRDSData->AF_Data.isMethod_A = 1;
1023                         else
1024                             pstRDSData->AF_Data.isMethod_A = 0;
1025                     }
1026
1027                     WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 isAFNum_Get:%d, isMethod_A:%d\n", pstRDSData->AF_Data.isAFNum_Get, pstRDSData->AF_Data.isMethod_A);
1028
1029                     //only one AF handle
1030                     if ((pstRDSData->AF_Data.isAFNum_Get) && (pstRDSData->AF_Data.AF_Num == 1)) {
1031                         pstRDSData->AF_Data.Addr_Cnt = 0xFF;
1032                         pstRDSData->event_status |= RDS_EVENT_AF_LIST;
1033                         WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 RDS_EVENT_AF_LIST update\n");
1034                     }
1035                 }
1036             }
1037                         else if ((pstRDSData->AF_Data.isAFNum_Get) && (pstRDSData->AF_Data.Addr_Cnt != 0xFF)) {
1038                 //AF Num correct
1039                 num = pstRDSData->AF_Data.AF_Num;
1040                 num = num >> 1;
1041                 WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 +num:%d\n", num);
1042
1043                 //Put AF freq fm_s32o buffer and check if AF freq is repeat again
1044                 for (indx = 1; indx < (num + 1); indx++) {
1045                     if ((AF_H == (pstRDSData->AF_Data.AF[0][2*indx-1])) && (AF_L == (pstRDSData->AF_Data.AF[0][2*indx]))) {
1046                         WCN_DBG(FM_ERR | RDSC, "RetrieveGroup0 AF same as indx:%d\n", indx);
1047                         break;
1048                     } else if (!(pstRDSData->AF_Data.AF[0][2*indx-1])) {
1049                         //null buffer
1050                         pstRDSData->AF_Data.AF[0][2*indx-1] = AF_H + 875; //convert to 100KHz
1051                         pstRDSData->AF_Data.AF[0][2*indx] = AF_L + 875;
1052                         
1053 #ifdef MTK_FM_50KHZ_SUPPORT
1054                         pstRDSData->AF_Data.AF[0][2*indx-1] *= 10;
1055                         pstRDSData->AF_Data.AF[0][2*indx] *= 10;
1056 #endif
1057                         WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 AF[0][%d]:%d, AF[0][%d]:%d\n",
1058                                 2*indx - 1, pstRDSData->AF_Data.AF[0][2*indx-1], 2*indx, pstRDSData->AF_Data.AF[0][2*indx]);
1059                         break;
1060                     }
1061                 }
1062
1063                 num = pstRDSData->AF_Data.AF_Num;
1064                 WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 ++num:%d\n", num);
1065
1066                 if (num > 0) {
1067                     if ((pstRDSData->AF_Data.AF[0][num-1]) != 0) {
1068                         num = num >> 1;
1069                         WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 +++num:%d\n", num);
1070
1071                         //arrange frequency from low to high:start
1072                         for (indx = 1; indx < num; indx++) {
1073                             for (indx2 = indx + 1; indx2 < (num + 1); indx2++) {
1074                                 AF_H = pstRDSData->AF_Data.AF[0][2*indx-1];
1075                                 AF_L = pstRDSData->AF_Data.AF[0][2*indx];
1076
1077                                 if (AF_H > (pstRDSData->AF_Data.AF[0][2*indx2-1])) {
1078                                     pstRDSData->AF_Data.AF[0][2*indx-1] = pstRDSData->AF_Data.AF[0][2*indx2-1];
1079                                     pstRDSData->AF_Data.AF[0][2*indx] = pstRDSData->AF_Data.AF[0][2*indx2];
1080                                     pstRDSData->AF_Data.AF[0][2*indx2-1] = AF_H;
1081                                     pstRDSData->AF_Data.AF[0][2*indx2] = AF_L;
1082                                 } else if (AF_H == (pstRDSData->AF_Data.AF[0][2*indx2-1])) {
1083                                     if (AF_L > (pstRDSData->AF_Data.AF[0][2*indx2])) {
1084                                         pstRDSData->AF_Data.AF[0][2*indx-1] = pstRDSData->AF_Data.AF[0][2*indx2-1];
1085                                         pstRDSData->AF_Data.AF[0][2*indx] = pstRDSData->AF_Data.AF[0][2*indx2];
1086                                         pstRDSData->AF_Data.AF[0][2*indx2-1] = AF_H;
1087                                         pstRDSData->AF_Data.AF[0][2*indx2] = AF_L;
1088                                     }
1089                                 }
1090                             }
1091                         }
1092
1093                         //arrange frequency from low to high:end
1094                         //compare AF buff0 and buff1 data:start
1095                         num = pstRDSData->AF_Data.AF_Num;
1096                         indx2 = 0;
1097
1098                         for (indx = 0; indx < num; indx++) {
1099                             if ((pstRDSData->AF_Data.AF[1][indx]) == (pstRDSData->AF_Data.AF[0][indx])) {
1100                                 if (pstRDSData->AF_Data.AF[1][indx] != 0)
1101                                     indx2++;
1102                             } else
1103                                 pstRDSData->AF_Data.AF[1][indx] = pstRDSData->AF_Data.AF[0][indx];
1104                         }
1105
1106                         WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 indx2:%d, num:%d\n", indx2, num);
1107
1108                         //compare AF buff0 and buff1 data:end
1109                         if (indx2 == num) {
1110                             pstRDSData->AF_Data.Addr_Cnt = 0xFF;
1111                             pstRDSData->event_status |= RDS_EVENT_AF_LIST;
1112                             WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 AF_Num:%d\n", pstRDSData->AF_Data.AF_Num);
1113
1114                             for (indx = 0; indx < num; indx++) {
1115                                 if ((pstRDSData->AF_Data.AF[1][indx]) == 0) {
1116                                     pstRDSData->AF_Data.Addr_Cnt = 0x0F;
1117                                     pstRDSData->event_status &= (~RDS_EVENT_AF_LIST);
1118                                 }
1119                             }
1120                         } else
1121                             pstRDSData->AF_Data.Addr_Cnt = 0x0F;
1122                     }
1123                 }
1124             }
1125         }
1126     }
1127
1128     return ret;
1129 }
1130
1131 static fm_s32 rds_retrieve_g0_di(fm_u16 *block_data, fm_u8 SubType, rds_t *pstRDSData)
1132 {
1133     fm_u8 DI_Code, DI_Flag;
1134     fm_s32 ret = 0;
1135 //    fm_bool valid = fm_false;
1136
1137     fm_u16 *event = &pstRDSData->event_status;
1138     fm_u32 *flag = &pstRDSData->RDSFlag.flag_status;
1139
1140     //parsing Program service name segment (in BlockD)
1141 //    ret = rds_checksum_check(block_data[4], FM_RDS_GDBK_IND_D, &valid);
1142
1143 //    if (valid == fm_false) {
1144 //        WCN_DBG(FM_WAR | RDSC, "Group0 BlockD crc err\n");
1145 //        return -FM_ECRC;
1146 //    }
1147
1148     rds_g0_ps_addr_get(block_data[1], &DI_Code);
1149     rds_g0_di_flag_get(block_data[1], &DI_Flag);
1150
1151     switch (DI_Code) {
1152     case 3:
1153
1154         if (pstRDSData->RDSFlag.Stereo != DI_Flag) {
1155             pstRDSData->RDSFlag.Stereo = DI_Flag;
1156             ret = rds_event_set(event, RDS_EVENT_FLAGS);
1157             ret = rds_flag_set(flag, RDS_FLAG_IS_STEREO);
1158         }
1159
1160         break;
1161     case 2:
1162
1163         if (pstRDSData->RDSFlag.Artificial_Head != DI_Flag) {
1164             pstRDSData->RDSFlag.Artificial_Head = DI_Flag;
1165             ret = rds_event_set(event, RDS_EVENT_FLAGS);
1166             ret = rds_flag_set(flag, RDS_FLAG_IS_ARTIFICIAL_HEAD);
1167         }
1168
1169         break;
1170     case 1:
1171
1172         if (pstRDSData->RDSFlag.Compressed != DI_Flag) {
1173             pstRDSData->RDSFlag.Compressed = DI_Flag;
1174             ret = rds_event_set(event, RDS_EVENT_FLAGS);
1175             ret = rds_flag_set(flag, RDS_FLAG_IS_COMPRESSED);
1176         }
1177
1178         break;
1179     case 0:
1180
1181         if (pstRDSData->RDSFlag.Dynamic_PTY != DI_Flag) {
1182             pstRDSData->RDSFlag.Dynamic_PTY = DI_Flag;
1183             ret = rds_event_set(event, RDS_EVENT_FLAGS);
1184             ret = rds_flag_set(flag, RDS_FLAG_IS_DYNAMIC_PTY);
1185         }
1186
1187         break;
1188     default:
1189         break;
1190     }
1191
1192     return ret;
1193 }
1194
1195 static fm_s32 rds_retrieve_g0_ps(fm_u16 *block_data, fm_u8 SubType, rds_t *pstRDSData)
1196 {
1197     fm_u8 ps_addr;
1198     fm_s32 ret = 0,i,num;
1199     fm_bool valid = fm_false;
1200 //    fm_s32 pos = 0;
1201     static struct fm_state_machine ps_sm = {
1202         .state = RDS_PS_START,
1203         .state_get = fm_state_get,
1204         .state_set = fm_state_set,
1205     };
1206 #if 0     
1207     static struct rds_bitmap ps_bm = {
1208         .bm = 0,
1209         .cnt = 0,
1210         .max_addr = 0x03,
1211         .bm_get = rds_bm_get,
1212         .bm_cnt_get = rds_bm_cnt_get,
1213         .bm_set = rds_bm_set,
1214         .bm_get_pos = rds_bm_get_pos,
1215         .bm_clr = rds_bm_clr,
1216         .bm_cmp = rds_bm_cmp,
1217     };
1218 #endif
1219     fm_u16 *event = &pstRDSData->event_status;
1220
1221     //parsing Program service name segment (in BlockD)
1222     ret = rds_checksum_check(block_data[4], FM_RDS_GDBK_IND_D, &valid);
1223
1224     if (valid == fm_false) {
1225         WCN_DBG(FM_WAR | RDSC, "Group0 BlockD crc err\n");
1226         return -FM_ECRC;
1227     }
1228
1229     rds_g0_ps_addr_get(block_data[1], &ps_addr);
1230
1231     //PS parsing state machine run
1232     while (1) {
1233         switch (STATE_GET(&ps_sm)) {
1234         case RDS_PS_START:
1235
1236             if (rds_g0_ps_get(block_data[4], block_data[3], ps_addr, pstRDSData->PS_Data.PS[0])) {
1237                 STATE_SET(&ps_sm, RDS_PS_FINISH); //if CRC error, we should not do parsing
1238                 break;
1239             }
1240
1241             rds_g0_ps_cmp(ps_addr, block_data[5], pstRDSData->PS_Data.PS[0],
1242                           pstRDSData->PS_Data.PS[1], pstRDSData->PS_Data.PS[2], /*&valid,*/&pstRDSData->PS_Data.Addr_Cnt);
1243
1244            // if (valid == fm_true) {
1245            //     ps_bm.bm_set(&ps_bm, ps_addr);
1246            // }
1247
1248             STATE_SET(&ps_sm, RDS_PS_DECISION);
1249             break;
1250         case RDS_PS_DECISION:
1251
1252             if (pstRDSData->PS_Data.Addr_Cnt == 0x000F) //get max  8 chars
1253                 //ps shouldn't check bm_cnt
1254                //     || (ps_bm.bm_cnt_get(&ps_bm) > RDS_RT_MULTI_REV_TH)) { //repeate many times, but no end char get
1255             {
1256                 //pos = ps_bm.bm_get_pos(&ps_bm);
1257                 STATE_SET(&ps_sm, RDS_PS_GETLEN);
1258             } 
1259                         else 
1260                         {
1261                 STATE_SET(&ps_sm, RDS_PS_FINISH);
1262             }
1263
1264             break;
1265         case RDS_PS_GETLEN:
1266             
1267             //if (pos == ps_bm.max_addr) 
1268                         {
1269                                 num=0;
1270                                 WCN_DBG(FM_NTC | RDSC, "PS[3]=%x %x %x %x %x %x %x %x\n", 
1271                                                                                 pstRDSData->PS_Data.PS[3][0],
1272                                                                                 pstRDSData->PS_Data.PS[3][1],
1273                                                                                 pstRDSData->PS_Data.PS[3][2],
1274                                                                                 pstRDSData->PS_Data.PS[3][3],
1275                                                                                 pstRDSData->PS_Data.PS[3][4],
1276                                                                                 pstRDSData->PS_Data.PS[3][5],
1277                                                                                 pstRDSData->PS_Data.PS[3][6],
1278                                                                                 pstRDSData->PS_Data.PS[3][7]);
1279                                 for(i=0;i<8;i++)//compare with last PS.
1280                                 {
1281                                         if(pstRDSData->PS_Data.PS[3][i]==pstRDSData->PS_Data.PS[2][i])
1282                                         {
1283                                                 num++;
1284                                         }
1285                                 }
1286                                 if(num != 8)
1287                                 {
1288                                         num=0;
1289                                         for(i=0;i<8;i++)
1290                                         {
1291                                                 if((pstRDSData->PS_Data.PS[2][i]==0x20)||(pstRDSData->PS_Data.PS[2][i]==0x0))
1292                                                 {
1293                                                         num++;
1294                                                 }
1295                                         }
1296                                         if(num != 8)
1297                                         {
1298                                                 fm_memcpy(pstRDSData->PS_Data.PS[3], pstRDSData->PS_Data.PS[2], 8);
1299                                                 rds_event_set(event, RDS_EVENT_PROGRAMNAME); //yes we got a new PS
1300                                                 WCN_DBG(FM_NTC | RDSC, "Yes, get an PS!\n");
1301                                         }
1302                                 }
1303                                 else
1304                                 {
1305                                         pstRDSData->PS_Data.Addr_Cnt=0;
1306                                         //clear buf
1307                                         fm_memset(pstRDSData->PS_Data.PS[0], 0x20, 8);
1308                                         fm_memset(pstRDSData->PS_Data.PS[1], 0x20, 8);
1309                                         fm_memset(pstRDSData->PS_Data.PS[2], 0x20, 8);
1310                                 }
1311             }
1312 #if 0
1313             ps_bm.bm_clr(&ps_bm);
1314             //clear buf
1315             fm_memset(pstRDSData->PS_Data.PS[0], 0x20, 8);
1316             fm_memset(pstRDSData->PS_Data.PS[1], 0x20, 8);
1317             fm_memset(pstRDSData->PS_Data.PS[2], 0x20, 8);
1318 #endif            
1319             STATE_SET(&ps_sm, RDS_PS_FINISH);
1320             break;
1321         case RDS_PS_FINISH:
1322             STATE_SET(&ps_sm, RDS_PS_START);
1323             goto out;
1324             break;
1325         default:
1326             break;
1327         }
1328     }
1329
1330 out:
1331     return ret;
1332 }
1333
1334 static fm_s32 rds_retrieve_g0(fm_u16 *block_data, fm_u8 SubType, rds_t *pstRDSData)
1335 {
1336     fm_s32 ret = 0;
1337
1338     ret = rds_retrieve_g0_af(block_data, SubType, pstRDSData);
1339
1340     if (ret) {
1341         return ret;
1342     }
1343
1344     ret = rds_retrieve_g0_di(block_data, SubType, pstRDSData);
1345
1346     if (ret) {
1347         return ret;
1348     }
1349
1350     ret = rds_retrieve_g0_ps(block_data, SubType, pstRDSData);
1351
1352     if (ret) {
1353         return ret;
1354     }
1355
1356     return ret;
1357 }
1358
1359 static fm_s32 rds_retrieve_g1(fm_u16 *block_data, fm_u8 SubType, rds_t *pstRDSData)
1360 {
1361     fm_u8 variant_code = (block_data[2] & 0x7000) >> 12;
1362     fm_s32 ret = 0;
1363
1364     if (variant_code == 0) {
1365         pstRDSData->Extend_Country_Code = (fm_u8)block_data[2] & 0xFF;
1366         WCN_DBG(FM_DBG | RDSC, "Extend_Country_Code:%d\n", pstRDSData->Extend_Country_Code);
1367     } else if (variant_code == 3) {
1368         pstRDSData->Language_Code = block_data[2] & 0xFFF;
1369         WCN_DBG(FM_DBG | RDSC, "Language_Code:%d\n", pstRDSData->Language_Code);
1370     }
1371
1372     pstRDSData->Radio_Page_Code = block_data[1] & 0x001F;
1373     pstRDSData->Program_Item_Number_Code = block_data[3];
1374
1375     return ret;
1376 }
1377
1378 static fm_s32 rds_retrieve_g2(fm_u16 *source, fm_u8 subtype, rds_t *target)
1379 {
1380     fm_s32 ret = 0;
1381     fm_u16 crc, cbc;
1382     fm_u16 blkA, blkB, blkC, blkD;
1383     fm_u8 *fresh, *once, *twice, *display;
1384     fm_u16 *event;
1385     fm_u32 *flag;
1386     static struct fm_state_machine rt_sm = {
1387         .state = RDS_RT_START,
1388         .state_get = fm_state_get,
1389         .state_set = fm_state_set,
1390     };
1391     static struct rds_bitmap rt_bm = {
1392         .bm = 0,
1393         .cnt = 0,
1394         .max_addr = 0xF,
1395         .bm_get = rds_bm_get,
1396         .bm_cnt_get = rds_bm_cnt_get,
1397         .bm_set = rds_bm_set,
1398         .bm_get_pos = rds_bm_get_pos,
1399         .bm_clr = rds_bm_clr,
1400         .bm_cmp = rds_bm_cmp,
1401     };
1402     fm_u8 rt_addr = 0;
1403     fm_bool txtAB_change = fm_false;  //text AB flag 0 --> 1 or 1-->0 meas new RT incoming
1404     fm_bool txt_end = fm_false;       //0x0D means text end
1405     fm_bool seg_ok = 0;
1406     fm_s32 pos = 0;
1407     fm_s32 rt_len = 0,indx=0,invalid_cnt=0;
1408     fm_s32 bufsize = 0;
1409
1410     FMR_ASSERT(source);
1411     FMR_ASSERT(target);
1412     //source
1413     blkA = source[0];
1414     blkB = source[1];
1415     blkC = source[2];
1416     blkD = source[3];
1417     crc = source[4];
1418     cbc = source[5];
1419     //target
1420     fresh = target->RT_Data.TextData[0];
1421     once = target->RT_Data.TextData[1];
1422     twice = target->RT_Data.TextData[2];
1423     display = target->RT_Data.TextData[3];
1424     event = &target->event_status;
1425     flag = &target->RDSFlag.flag_status;
1426     bufsize = sizeof(target->RT_Data.TextData[0]);
1427         rt_bm.bm = target->RT_Data.Addr_Cnt;
1428
1429     //get basic info: addr, txtAB
1430     if (rds_g2_rt_addr_get(blkB, &rt_addr))
1431         return ret;
1432
1433     if (rds_g2_txtAB_get(blkB, &target->RDSFlag.Text_AB, &txtAB_change))
1434         return ret;
1435         if(txtAB_change == fm_true)
1436         {
1437                 //clear buf
1438                 fm_memset(fresh, 0x20, bufsize);
1439                 fm_memset(once, 0x20, bufsize);
1440                 fm_memset(twice, 0x20, bufsize);
1441                 rt_bm.bm_clr(&rt_bm);
1442         }
1443     //RT parsing state machine run
1444     while (1) {
1445         switch (STATE_GET(&rt_sm)) {
1446         case RDS_RT_START:
1447                 {
1448 #if 0
1449             if (txtAB_change == fm_true)
1450             {
1451                 STATE_SET(&rt_sm, RDS_RT_DECISION);
1452             } 
1453             else 
1454 #endif
1455             {
1456                 if (rds_g2_rt_get(crc, subtype, blkC, blkD, rt_addr, fresh) == 0) 
1457                 {
1458                     //STATE_SET(&rt_sm, RDS_RT_FINISH); //if CRC error, we should not do parsing
1459                     //break;
1460                                         rds_g2_rt_cmp(rt_addr, cbc, subtype, fresh, once, twice,
1461                                                                   &seg_ok/*, &txt_end, &rt_len*/);
1462                                         
1463                                         if (seg_ok == fm_true) 
1464                                         {
1465                                                 rt_bm.bm_set(&rt_bm, rt_addr);
1466                                         }
1467                                         else//clear bitmap of rt_addr
1468                                         {
1469                                                 rt_bm.bm &= ~(1<<rt_addr);
1470                                         }
1471                 }
1472                                 WCN_DBG(FM_NTC | RDSC, "bitmap=0x%04x, bmcnt=%d\n", rt_bm.bm, rt_bm.cnt);
1473                                 rds_g2_rt_check_end(rt_addr,subtype,twice,&txt_end);
1474
1475                 STATE_SET(&rt_sm, RDS_RT_DECISION);
1476             }
1477                         break;
1478                 }
1479         case RDS_RT_DECISION:
1480                 {
1481                         if ((txt_end == fm_true)
1482                                 || (rt_bm.bm_get(&rt_bm) == 0xFFFF) //get max  64 chars
1483                                 || (rt_bm.bm_cnt_get(&rt_bm) > RDS_RT_MULTI_REV_TH))//repeate many times, but no end char get
1484             { 
1485                 pos = rt_bm.bm_get_pos(&rt_bm);
1486                 rds_g2_rt_get_len(subtype, pos, &rt_len);
1487                 STATE_SET(&rt_sm, RDS_RT_GETLEN);
1488             } 
1489             else 
1490             {
1491                 STATE_SET(&rt_sm, RDS_RT_FINISH);
1492             }
1493
1494             break;
1495                 }
1496         case RDS_RT_GETLEN:
1497             
1498             if (rt_len > 0 /*&& ((txt_end == fm_true) || (rt_bm.bm_get(&rt_bm) == 0xFFFF))*/) 
1499             {
1500                                 for(indx=0; indx<rt_len; indx++)
1501                                 {
1502                                         if(twice[indx] == 0x20)
1503                                                 invalid_cnt++;
1504                                 }       
1505                                 if(invalid_cnt != rt_len)
1506                                 {
1507                                         if(memcmp(display,twice,bufsize)!=0)
1508                                         {
1509                                                 fm_memcpy(display, twice, bufsize);
1510                                                 target->RT_Data.TextLength = rt_len;
1511                                 rds_event_set(event, RDS_EVENT_LAST_RADIOTEXT); //yes we got a new RT
1512                                 WCN_DBG(FM_NTC | RDSC, "Yes, get an RT! [len=%d]\n", rt_len);
1513                                         }
1514                                         rt_bm.bm_clr(&rt_bm);
1515                                         //clear buf
1516                                         fm_memset(fresh, 0x20, bufsize);
1517                                         fm_memset(once, 0x20, bufsize);
1518                                         fm_memset(twice, 0x20, bufsize);
1519                 }
1520                 else
1521                         WCN_DBG(FM_NTC | RDSC, "Get 0x20 RT %d\n", invalid_cnt);
1522             }
1523
1524 #if 0
1525             if (txtAB_change == fm_true) {
1526                 txtAB_change = fm_false;
1527                 //we need get new RT after show the old RT to the display
1528                 STATE_SET(&rt_sm, RDS_RT_START);
1529             } 
1530             else 
1531 #endif
1532             {
1533                 STATE_SET(&rt_sm, RDS_RT_FINISH);
1534             }
1535             break;
1536         case RDS_RT_FINISH:
1537             STATE_SET(&rt_sm, RDS_RT_START);
1538             goto out;
1539             break;
1540         default:
1541             break;
1542         }
1543     }
1544
1545 out:
1546         target->RT_Data.Addr_Cnt = rt_bm.bm;
1547     return ret;
1548 }
1549
1550 static fm_s32 rds_retrieve_g4(fm_u16 *block_data, fm_u8 SubType, rds_t *pstRDSData)
1551 {
1552     fm_u16 year, month, k = 0, D2, minute;
1553     fm_u32 MJD, D1;
1554     fm_s32 ret = 0;
1555     WCN_DBG(FM_DBG | RDSC, "RetrieveGroup4 %d\n", SubType);
1556
1557     if (!SubType) {
1558         //Type A
1559         if ((block_data[4]&FM_RDS_GDBK_IND_C) && (block_data[4]&FM_RDS_GDBK_IND_D)) {
1560             MJD = (fm_u32)(((block_data[1] & 0x0003) << 15) + ((block_data[2] & 0xFFFE) >> 1));
1561             year = (MJD * 100 - 1507820) / 36525;
1562             month = (MJD * 10000 - 149561000 - 3652500 * year) / 306001;
1563
1564             if ((month == 14) || (month == 15))
1565                 k = 1;
1566
1567             D1 = (fm_u32)((36525 * year) / 100);
1568             D2 = (fm_u16)((306001 * month) / 10000);
1569             pstRDSData->CT.Year = 1900 + year + k;
1570             pstRDSData->CT.Month = month - 1 - k * 12;
1571             pstRDSData->CT.Day = (fm_u16)(MJD - 14956 - D1 - D2);
1572             pstRDSData->CT.Hour = ((block_data[2] & 0x0001) << 4) + ((block_data[3] & 0xF000) >> 12);
1573             minute = (block_data[3] & 0x0FC0) >> 6;
1574
1575             if (block_data[3]&0x0020) {
1576                 pstRDSData->CT.Local_Time_offset_signbit = 1; //0=+, 1=-
1577             }
1578
1579             pstRDSData->CT.Local_Time_offset_half_hour = block_data[3] & 0x001F;
1580
1581             if (pstRDSData->CT.Minute != minute) {
1582                 pstRDSData->CT.Minute = (block_data[3] & 0x0FC0) >> 6;
1583                 pstRDSData->event_status |= RDS_EVENT_UTCDATETIME;
1584             }
1585         }
1586     }
1587
1588     return ret;
1589 }
1590
1591 static fm_s32 rds_retrieve_g14(fm_u16 *block_data, fm_u8 SubType, rds_t *pstRDSData)
1592 {
1593     static fm_s16 preAFON_Num = 0;
1594     fm_u8 TP_ON, TA_ON, PI_ON, PS_Num, AF_H, AF_L, indx, indx2, num;
1595     fm_s32 ret = 0;
1596     WCN_DBG(FM_DBG | RDSC, "RetrieveGroup14 %d\n", SubType);
1597     //SubType = (*(block_data+1)&0x0800)>>11;
1598     PI_ON = block_data[3];
1599     TP_ON = block_data[1] & 0x0010;
1600
1601     if ((!SubType) && (block_data[4]&FM_RDS_GDBK_IND_C)) {
1602         //Type A
1603         PS_Num = block_data[1] & 0x000F;
1604
1605         if (PS_Num < 4) {
1606             for (indx = 0; indx < 2; indx++) {
1607                 pstRDSData->PS_ON[2*PS_Num] = block_data[2] >> 8;
1608                 pstRDSData->PS_ON[2*PS_Num+1] = block_data[2] & 0xFF;
1609             }
1610         } else if (PS_Num == 4) {
1611             AF_H = (block_data[2] & 0xFF00) >> 8;
1612             AF_L = block_data[2] & 0x00FF;
1613
1614             if ((AF_H > 224) && (AF_H < 250)) {
1615                 //Followed AF Number
1616                 pstRDSData->AFON_Data.isAFNum_Get = 0;
1617                 preAFON_Num = AF_H - 224;
1618
1619                 if (pstRDSData->AFON_Data.AF_Num != preAFON_Num) {
1620                     pstRDSData->AFON_Data.AF_Num = preAFON_Num;
1621                 } else
1622                     pstRDSData->AFON_Data.isAFNum_Get = 1;
1623
1624                 if (AF_L < 205) {
1625                     pstRDSData->AFON_Data.AF[0][0] = AF_L + 875;
1626
1627                     if ((pstRDSData->AFON_Data.AF[0][0]) != (pstRDSData->AFON_Data.AF[1][0])) {
1628                         pstRDSData->AFON_Data.AF[1][0] = pstRDSData->AFON_Data.AF[0][0];
1629                     } else {
1630                         pstRDSData->AFON_Data.isMethod_A = 1;
1631                     }
1632                 }
1633             }
1634                         else if ((pstRDSData->AFON_Data.isAFNum_Get) && ((pstRDSData->AFON_Data.Addr_Cnt) != 0xFF)) {
1635                 //AF Num correct
1636                 num = pstRDSData->AFON_Data.AF_Num;
1637                 num = num >> 1;
1638
1639                 //Put AF freq fm_s32o buffer and check if AF freq is repeat again
1640                 for (indx = 1; indx < (num + 1); indx++) {
1641                     if ((AF_H == (pstRDSData->AFON_Data.AF[0][2*indx-1])) && (AF_L == (pstRDSData->AFON_Data.AF[0][2*indx]))) {
1642                         WCN_DBG(FM_NTC | RDSC, "RetrieveGroup14 AFON same as indx:%d\n", indx);
1643                         break;
1644                     } else if (!(pstRDSData->AFON_Data.AF[0][2*indx-1])) {
1645                         //null buffer
1646                         pstRDSData->AFON_Data.AF[0][2*indx-1] = AF_H + 875;
1647                         pstRDSData->AFON_Data.AF[0][2*indx] = AF_L + 875;
1648                         break;
1649                     }
1650                 }
1651
1652                 num = pstRDSData->AFON_Data.AF_Num;
1653
1654                 if (num > 0) {
1655                     if ((pstRDSData->AFON_Data.AF[0][num-1]) != 0) {
1656                         num = num >> 1;
1657
1658                         //arrange frequency from low to high:start
1659                         for (indx = 1; indx < num; indx++) {
1660                             for (indx2 = indx + 1; indx2 < (num + 1); indx2++) {
1661                                 AF_H = pstRDSData->AFON_Data.AF[0][2*indx-1];
1662                                 AF_L = pstRDSData->AFON_Data.AF[0][2*indx];
1663
1664                                 if (AF_H > (pstRDSData->AFON_Data.AF[0][2*indx2-1])) {
1665                                     pstRDSData->AFON_Data.AF[0][2*indx-1] = pstRDSData->AFON_Data.AF[0][2*indx2-1];
1666                                     pstRDSData->AFON_Data.AF[0][2*indx] = pstRDSData->AFON_Data.AF[0][2*indx2];
1667                                     pstRDSData->AFON_Data.AF[0][2*indx2-1] = AF_H;
1668                                     pstRDSData->AFON_Data.AF[0][2*indx2] = AF_L;
1669                                 } else if (AF_H == (pstRDSData->AFON_Data.AF[0][2*indx2-1])) {
1670                                     if (AF_L > (pstRDSData->AFON_Data.AF[0][2*indx2])) {
1671                                         pstRDSData->AFON_Data.AF[0][2*indx-1] = pstRDSData->AFON_Data.AF[0][2*indx2-1];
1672                                         pstRDSData->AFON_Data.AF[0][2*indx] = pstRDSData->AFON_Data.AF[0][2*indx2];
1673                                         pstRDSData->AFON_Data.AF[0][2*indx2-1] = AF_H;
1674                                         pstRDSData->AFON_Data.AF[0][2*indx2] = AF_L;
1675                                     }
1676                                 }
1677                             }
1678                         }
1679
1680                         //arrange frequency from low to high:end
1681                         //compare AF buff0 and buff1 data:start
1682                         num = pstRDSData->AFON_Data.AF_Num;
1683                         indx2 = 0;
1684
1685                         for (indx = 0; indx < num; indx++) {
1686                             if ((pstRDSData->AFON_Data.AF[1][indx]) == (pstRDSData->AFON_Data.AF[0][indx])) {
1687                                 if (pstRDSData->AFON_Data.AF[1][indx] != 0)
1688                                     indx2++;
1689                             } else
1690                                 pstRDSData->AFON_Data.AF[1][indx] = pstRDSData->AFON_Data.AF[0][indx];
1691                         }
1692
1693                         //compare AF buff0 and buff1 data:end
1694                         if (indx2 == num) {
1695                             pstRDSData->AFON_Data.Addr_Cnt = 0xFF;
1696                             pstRDSData->event_status |= RDS_EVENT_AFON_LIST;
1697
1698                             for (indx = 0; indx < num; indx++) {
1699                                 if ((pstRDSData->AFON_Data.AF[1][indx]) == 0) {
1700                                     pstRDSData->AFON_Data.Addr_Cnt = 0x0F;
1701                                     pstRDSData->event_status &= (~RDS_EVENT_AFON_LIST);
1702                                 }
1703                             }
1704                         } else
1705                             pstRDSData->AFON_Data.Addr_Cnt = 0x0F;
1706                     }
1707                 }
1708             }
1709         }
1710     } else {
1711         //Type B
1712         TA_ON = block_data[1] & 0x0008;
1713         WCN_DBG(FM_DBG | RDSC, "TA g14 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);
1714
1715         if ((!pstRDSData->RDSFlag.TP) && (pstRDSData->RDSFlag.TA) && TP_ON && TA_ON) {
1716             fm_s32 TA_num = 0;
1717
1718             for (num = 0; num < 25; num++) {
1719                 if (pstRDSData->AFON_Data.AF[1][num] != 0) {
1720                     TA_num++;
1721                 } else {
1722                     break;
1723                 }
1724             }
1725
1726             WCN_DBG(FM_NTC | RDSC, "TA set RDS_EVENT_TAON");
1727
1728             if (TA_num == pstRDSData->AFON_Data.AF_Num) {
1729                 pstRDSData->event_status |= RDS_EVENT_TAON;
1730             }
1731         }
1732     }
1733
1734     return ret;
1735 }
1736
1737 /*
1738  *  rds_parser
1739  *  Block0:     PI code(16bits)
1740  *  Block1:     Group type(4bits), B0=version code(1bit), TP=traffic program code(1bit),
1741  *  PTY=program type code(5bits), other(5bits)
1742  *  Block2:     16bits
1743  *  Block3:     16bits
1744  *  @rds_dst - target buffer that record RDS parsing result
1745  *  @rds_raw - rds raw data
1746  *  @rds_size - size of rds raw data
1747  *  @getfreq - function pointer, AF need get current freq
1748  */
1749 fm_s32 rds_parser(rds_t *rds_dst, struct rds_rx_t *rds_raw, fm_s32 rds_size, fm_u16(*getfreq)(void))
1750 {
1751     fm_s32 ret = 0;
1752     //block_data[0] = blockA,   block_data[1] = blockB, block_data[2] = blockC,   block_data[3] = blockD,
1753     //block_data[4] = CRC,      block_data[5] = CBC
1754     fm_u16 block_data[6];
1755     fm_u8 GroupType, SubType = 0;
1756     fm_s32 rds_cnt = 0;
1757     fm_s32 i = 0;
1758     fm_bool dirty = fm_false;
1759     //target buf to fill the result in
1760     fm_u16 *event = &rds_dst->event_status;
1761     fm_u32 *flag = &rds_dst->RDSFlag.flag_status;
1762
1763     FMR_ASSERT(getfreq);
1764     rds_get_freq = getfreq;
1765
1766     ret = rds_cnt_get(rds_raw, rds_size, &rds_cnt);
1767
1768     if (ret) {
1769         WCN_DBG(FM_WAR | RDSC, "get cnt err[ret=%d]\n", ret);
1770         return ret;
1771     }
1772
1773     while (rds_cnt > 0) {
1774         ret = rds_grp_get(&block_data[0], rds_raw, i);
1775
1776         if (ret) {
1777             WCN_DBG(FM_WAR | RDSC, "get group err[ret=%d]\n", ret);
1778             goto do_next;
1779         }
1780
1781         ret = rds_grp_type_get(block_data[4], block_data[1], &GroupType, &SubType);
1782
1783         if (ret) {
1784             WCN_DBG(FM_WAR | RDSC, "get group type err[ret=%d]\n", ret);
1785             goto do_next;
1786         }
1787
1788         ret = rds_grp_counter_add(GroupType, SubType, &rds_dst->gc);
1789
1790         ret = rds_grp_pi_get(block_data[4], block_data[0], &rds_dst->PI, &dirty);
1791
1792         if (ret) {
1793             WCN_DBG(FM_WAR | RDSC, "get group pi err[ret=%d]\n", ret);
1794             goto do_next;
1795         } else if (dirty == fm_true) {
1796             ret = rds_event_set(event, RDS_EVENT_PI_CODE); //yes, we got new PI code
1797         }
1798
1799         ret = rds_grp_pty_get(block_data[4], block_data[1], &rds_dst->PTY, &dirty);
1800
1801         if (ret) {
1802             WCN_DBG(FM_WAR | RDSC, "get group pty err[ret=%d]\n", ret);
1803             goto do_next;
1804         } else if (dirty == fm_true) {
1805             ret = rds_event_set(event, RDS_EVENT_PTY_CODE); // yes, we got new PTY code
1806         }
1807
1808         ret = rds_grp_tp_get(block_data[4], block_data[1], &rds_dst->RDSFlag.TP, &dirty);
1809
1810         if (ret) {
1811             WCN_DBG(FM_WAR | RDSC, "get group tp err[ret=%d]\n", ret);
1812             goto do_next;
1813         } else if (dirty == fm_true) {
1814             ret = rds_event_set(event, RDS_EVENT_FLAGS); // yes, we got new TP code
1815             ret = rds_flag_set(flag, RDS_FLAG_IS_TP);
1816         }
1817
1818         switch (GroupType) {
1819         case 0:
1820
1821             if ((ret = rds_retrieve_g0(&block_data[0], SubType, rds_dst)))
1822                 goto do_next;
1823
1824             break;
1825         case 1:
1826
1827             if ((ret = rds_retrieve_g1(&block_data[0], SubType, rds_dst)))
1828                 goto do_next;
1829
1830             break;
1831         case 2:
1832
1833             if ((ret = rds_retrieve_g2(&block_data[0], SubType, rds_dst)))
1834                 goto do_next;
1835
1836             break;
1837         case 4:
1838
1839             if ((ret = rds_retrieve_g4(&block_data[0], SubType, rds_dst)))
1840                 goto do_next;
1841
1842             break;
1843         case 14:
1844
1845             if ((ret = rds_retrieve_g14(&block_data[0], SubType, rds_dst)))
1846                 goto do_next;
1847
1848             break;
1849         default:
1850             break;
1851         }
1852
1853 do_next:
1854
1855         if (ret && (ret != -FM_ECRC)) {
1856             WCN_DBG(FM_ERR | RDSC, "parsing err[ret=%d]\n", ret);
1857             return ret;
1858         }
1859
1860         rds_cnt--;
1861         i++;
1862     }
1863
1864     return ret;
1865 }
1866
1867