1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef __FM_H__
18 #define __FM_H__
19 
20 #include <linux/ioctl.h>
21 #include <linux/time.h>
22 
23 typedef signed char fm_s8;
24 typedef signed short fm_s16;
25 typedef signed int fm_s32;
26 typedef signed long long fm_s64;
27 typedef unsigned char fm_u8;
28 typedef unsigned short fm_u16;
29 typedef unsigned int fm_u32;
30 typedef unsigned long long fm_u64;
31 typedef enum fm_bool {
32     fm_false = 0,
33     fm_true  = 1
34 } fm_bool;
35 
36 // scan sort algorithm
37 enum {
38     FM_SCAN_SORT_NON = 0,
39     FM_SCAN_SORT_UP,
40     FM_SCAN_SORT_DOWN,
41     FM_SCAN_SORT_MAX
42 };
43 
44 // scan methods
45 enum {
46     FM_SCAN_SEL_HW = 0, // select hardware scan, advantage: fast
47     FM_SCAN_SEL_SW, // select software scan, advantage: more accurate
48     FM_SCAN_SEL_MAX
49 };
50 
51 //*****************************************************************************************
52 //***********************************FM config for customer *******************************
53 //*****************************************************************************************
54 #define FMR_RSSI_TH_LONG    0x0301 // FM radio long antenna RSSI threshold(11.375dBuV)
55 #define FMR_RSSI_TH_SHORT   0x02E0 // FM radio short antenna RSSI threshold(-1dBuV)
56 #define FMR_CQI_TH          0x00E9 // FM radio Channel quality indicator threshold(0x0000~0x00FF)
57 #define FMR_SEEK_SPACE      1 // FM radio seek space,1:100KHZ; 2:200KHZ
58 #define FMR_SCAN_CH_SIZE    40 // FM radio scan max channel size
59 #define FMR_BAND            1 // FM radio band, 1:87.5MHz~108.0MHz; 2:76.0MHz~90.0MHz;
60                               // 3:76.0MHz~108.0MHz; 4:special
61 #define FMR_BAND_FREQ_L     875 // FM radio special band low freq(Default 87.5MHz)
62 #define FMR_BAND_FREQ_H     1080 // FM radio special band high freq(Default 108.0MHz)
63 #define FM_SCAN_SORT_SELECT FM_SCAN_SORT_NON
64 #define FM_SCAN_SELECT      FM_SCAN_SEL_HW
65 #define FM_SCAN_SOFT_MUTE_GAIN_TH  3 // soft-mute threshold when software scan, rang: 0~3,
66                                      // 0 means better audio quality but less channel
67 #define FM_CHIP_DESE_RSSI_TH (-102) // rang: -102 ~ -72
68 
69 //*****************************************************************************************
70 //***********************************FM config for engineer *******************************
71 //*****************************************************************************************
72 #define FMR_MR_TH           0x01BD // FM radio MR threshold
73 #define ADDR_SCAN_TH        0xE0 // scan thrshold register
74 #define ADDR_CQI_TH         0xE1 // scan CQI register
75 //*****************************************************************************************
76 
77 #define FM_NAME             "fm"
78 #define FM_DEVICE_NAME      "/dev/fm"
79 
80 // errno
81 #define FM_SUCCESS      0
82 #define FM_FAILED       1
83 #define FM_EPARM        2
84 #define FM_BADSTATUS    3
85 #define FM_TUNE_FAILED  4
86 #define FM_SEEK_FAILED  5
87 #define FM_BUSY         6
88 #define FM_SCAN_FAILED  7
89 
90 // band
91 #define FM_BAND_UNKNOWN 0
92 #define FM_BAND_UE      1 // US/Europe band  87.5MHz ~ 108MHz (DEFAULT)
93 #define FM_BAND_JAPAN   2 // Japan band      76MHz   ~ 90MHz
94 #define FM_BAND_JAPANW  3 // Japan wideband  76MHZ   ~ 108MHz
95 #define FM_BAND_SPECIAL 4 // special   band  between 76MHZ   and  108MHz
96 #define FM_BAND_DEFAULT FM_BAND_UE
97 
98 #define FM_UE_FREQ_MIN  875
99 #define FM_UE_FREQ_MAX  1080
100 #define FM_JP_FREQ_MIN  760
101 #define FM_JP_FREQ_MAX  1080
102 #define FM_FREQ_MIN  FMR_BAND_FREQ_L
103 #define FM_FREQ_MAX  FMR_BAND_FREQ_H
104 #define FM_RAIDO_BAND FM_BAND_UE
105 
106 // space
107 #define FM_SPACE_UNKNOWN    0
108 #define FM_SPACE_100K       1
109 #define FM_SPACE_200K       2
110 #define FM_SPACE_50K        5
111 #define FM_SPACE_DEFAULT    FM_SPACE_100K
112 
113 #define FM_SEEK_SPACE FMR_SEEK_SPACE
114 
115 // max scan channel num
116 #define FM_MAX_CHL_SIZE FMR_SCAN_CH_SIZE
117 // auto HiLo
118 #define FM_AUTO_HILO_OFF    0
119 #define FM_AUTO_HILO_ON     1
120 
121 // seek direction
122 #define FM_SEEK_UP          0
123 #define FM_SEEK_DOWN        1
124 
125 // seek threshold
126 #define FM_SEEKTH_LEVEL_DEFAULT 4
127 
128 struct fm_tune_parm {
129     uint8_t err;
130     uint8_t band;
131     uint8_t space;
132     uint8_t hilo;
133     uint16_t freq;
134 };
135 
136 struct fm_seek_parm {
137     uint8_t err;
138     uint8_t band;
139     uint8_t space;
140     uint8_t hilo;
141     uint8_t seekdir;
142     uint8_t seekth;
143     uint16_t freq;
144 };
145 
146 struct fm_scan_parm {
147     uint8_t  err;
148     uint8_t  band;
149     uint8_t  space;
150     uint8_t  hilo;
151     uint16_t freq;
152     uint16_t ScanTBL[16];
153     uint16_t ScanTBLSize;
154 };
155 
156 struct fm_ch_rssi {
157     uint16_t freq;
158     int rssi;
159 };
160 
161 enum fm_scan_cmd_t {
162     FM_SCAN_CMD_INIT = 0,
163     FM_SCAN_CMD_START,
164     FM_SCAN_CMD_GET_NUM,
165     FM_SCAN_CMD_GET_CH,
166     FM_SCAN_CMD_GET_RSSI,
167     FM_SCAN_CMD_GET_CH_RSSI,
168     FM_SCAN_CMD_MAX
169 };
170 
171 struct fm_scan_t {
172     enum fm_scan_cmd_t cmd;
173     int ret; // 0, success; else error code
174     uint16_t lower; // lower band, Eg, 7600 -> 76.0Mhz
175     uint16_t upper; // upper band, Eg, 10800 -> 108.0Mhz
176     int space; // 5: 50KHz, 10: 100Khz, 20: 200Khz
177     int num; // valid channel number
178     void *priv;
179     int sr_size; // scan result buffer size in bytes
180     union {
181         uint16_t *ch_buf; // channel buffer
182         int *rssi_buf; // rssi buffer
183         struct fm_ch_rssi *ch_rssi_buf; //channel and RSSI buffer
184     } sr;
185 };
186 
187 struct fm_seek_t {
188     int ret; // 0, success; else error code
189     uint16_t freq;
190     uint16_t lower; // lower band, Eg, 7600 -> 76.0Mhz
191     uint16_t upper; // upper band, Eg, 10800 -> 108.0Mhz
192     int space; // 5: 50KHz, 10: 100Khz, 20: 200Khz
193     int dir; // 0: up; 1: down
194     int th; // seek threshold in dbm(Eg, -95dbm)
195     void *priv;
196 };
197 
198 struct fm_tune_t {
199     int ret; // 0, success; else error code
200     uint16_t freq;
201     uint16_t lower; // lower band, Eg, 7600 -> 76.0Mhz
202     uint16_t upper; // upper band, Eg, 10800 -> 108.0Mhz
203     int space; // 5: 50KHz, 10: 100Khz, 20: 200Khz
204     void *priv;
205 };
206 
207 struct fm_softmute_tune_t {
208     fm_s32 rssi; // RSSI of current channel
209     fm_u16 freq; // current frequency
210     fm_bool valid; // current channel is valid(true) or not(false)
211 };
212 
213 struct fm_rssi_req {
214     uint16_t num;
215     uint16_t read_cnt;
216     struct fm_ch_rssi cr[16*16];
217 };
218 
219 struct fm_hw_info {
220     int chip_id;
221     int eco_ver;
222     int rom_ver;
223     int patch_ver;
224     int reserve;
225 };
226 
227 struct fm_search_threshold_t {
228     fm_s32 th_type;// 0, RSSI. 1,desense RSSI. 2,SMG.
229     fm_s32 th_val; //threshold value
230     fm_s32 reserve;
231 };
232 
233 #define NEED_DEF_RDS 1
234 
235 #if NEED_DEF_RDS
236 //For RDS feature
237 typedef struct {
238     uint8_t TP;
239     uint8_t TA;
240     uint8_t Music;
241     uint8_t Stereo;
242     uint8_t Artificial_Head;
243     uint8_t Compressed;
244     uint8_t Dynamic_PTY;
245     uint8_t Text_AB;
246     uint32_t flag_status;
247 } RDSFlag_Struct;
248 
249 typedef struct {
250     uint16_t Month;
251     uint16_t Day;
252     uint16_t Year;
253     uint16_t Hour;
254     uint16_t Minute;
255     uint8_t Local_Time_offset_signbit;
256     uint8_t Local_Time_offset_half_hour;
257 } CT_Struct;
258 
259 typedef struct {
260     int16_t AF_Num;
261     int16_t AF[2][25];
262     uint8_t Addr_Cnt;
263     uint8_t isMethod_A;
264     uint8_t isAFNum_Get;
265 } AF_Info;
266 
267 typedef struct {
268     uint8_t PS[4][8];
269     uint8_t Addr_Cnt;
270 } PS_Info;
271 
272 typedef struct {
273     uint8_t TextData[4][64];
274     uint8_t GetLength;
275     uint8_t isRTDisplay;
276     uint8_t TextLength;
277     uint8_t isTypeA;
278     uint8_t BufCnt;
279     uint16_t Addr_Cnt;
280 } RT_Info;
281 
282 struct rds_raw_data {
283     int dirty; // indicate if the data changed or not
284     int len; // the data len form chip
285     uint8_t data[146];
286 };
287 
288 struct rds_group_cnt {
289     unsigned long total;
290     unsigned long groupA[16]; // RDS groupA counter
291     unsigned long groupB[16]; // RDS groupB counter
292 };
293 
294 enum rds_group_cnt_opcode {
295     RDS_GROUP_CNT_READ = 0,
296     RDS_GROUP_CNT_WRITE,
297     RDS_GROUP_CNT_RESET,
298     RDS_GROUP_CNT_MAX
299 };
300 
301 struct rds_group_cnt_req {
302     int err;
303     enum rds_group_cnt_opcode op;
304     struct rds_group_cnt gc;
305 };
306 
307 typedef struct {
308     CT_Struct CT;
309     RDSFlag_Struct RDSFlag;
310     uint16_t PI;
311     uint8_t Switch_TP;
312     uint8_t PTY;
313     AF_Info AF_Data;
314     AF_Info AFON_Data;
315     uint8_t Radio_Page_Code;
316     uint16_t Program_Item_Number_Code;
317     uint8_t Extend_Country_Code;
318     uint16_t Language_Code;
319     PS_Info PS_Data;
320     uint8_t PS_ON[8];
321     RT_Info RT_Data;
322     uint16_t event_status;
323     struct rds_group_cnt gc;
324 } RDSData_Struct;
325 
326 //valid Rds Flag for notify
327 typedef enum {
328     RDS_FLAG_IS_TP              = 0x0001, // Program is a traffic program
329     RDS_FLAG_IS_TA              = 0x0002, // Program currently broadcasts a traffic ann.
330     RDS_FLAG_IS_MUSIC           = 0x0004, // Program currently broadcasts music
331     RDS_FLAG_IS_STEREO          = 0x0008, // Program is transmitted in stereo
332     RDS_FLAG_IS_ARTIFICIAL_HEAD = 0x0010, // Program is an artificial head recording
333     RDS_FLAG_IS_COMPRESSED      = 0x0020, // Program content is compressed
334     RDS_FLAG_IS_DYNAMIC_PTY     = 0x0040, // Program type can change
335     RDS_FLAG_TEXT_AB            = 0x0080  // If this flag changes state, a new radio text string begins
336 } RdsFlag;
337 
338 typedef enum {
339     RDS_EVENT_FLAGS          = 0x0001, // One of the RDS flags has changed state
340     RDS_EVENT_PI_CODE        = 0x0002, // The program identification code has changed
341     RDS_EVENT_PTY_CODE       = 0x0004, // The program type code has changed
342     RDS_EVENT_PROGRAMNAME    = 0x0008, // The program name has changed
343     RDS_EVENT_UTCDATETIME    = 0x0010, // A new UTC date/time is available
344     RDS_EVENT_LOCDATETIME    = 0x0020, // A new local date/time is available
345     RDS_EVENT_LAST_RADIOTEXT = 0x0040, // A radio text string was completed
346     RDS_EVENT_AF             = 0x0080, // Current Channel RF signal strength too weak, need do AF switch
347     RDS_EVENT_AF_LIST        = 0x0100, // An alternative frequency list is ready
348     RDS_EVENT_AFON_LIST      = 0x0200, // An alternative frequency list is ready
349     RDS_EVENT_TAON           = 0x0400,  // Other Network traffic announcement start
350     RDS_EVENT_TAON_OFF       = 0x0800, // Other Network traffic announcement finished.
351     RDS_EVENT_RDS            = 0x2000, // RDS Interrupt had arrived durint timer period
352     RDS_EVENT_NO_RDS         = 0x4000, // RDS Interrupt not arrived durint timer period
353     RDS_EVENT_RDS_TIMER      = 0x8000 // Timer for RDS Bler Check. ---- BLER  block error rate
354 } RdsEvent;
355 #endif
356 
357 typedef enum {
358     FM_I2S_ON = 0,
359     FM_I2S_OFF,
360     FM_I2S_STATE_ERR
361 } fm_i2s_state_e;
362 
363 typedef enum {
364     FM_I2S_MASTER = 0,
365     FM_I2S_SLAVE,
366     FM_I2S_MODE_ERR
367 } fm_i2s_mode_e;
368 
369 typedef enum {
370     FM_I2S_32K = 0,
371     FM_I2S_44K,
372     FM_I2S_48K,
373     FM_I2S_SR_ERR
374 } fm_i2s_sample_e;
375 
376 struct fm_i2s_setting {
377     int onoff;
378     int mode;
379     int sample;
380 };
381 
382 typedef enum {
383     FM_RX = 0,
384     FM_TX = 1
385 } FM_PWR_T;
386 
387 typedef struct fm_i2s_info {
388     int status; /* 0:FM_I2S_ON, 1:FM_I2S_OFF,2:error */
389     int mode; /* 0:FM_I2S_MASTER, 1:FM_I2S_SLAVE,2:error */
390     int rate; /* 0:FM_I2S_32K:32000,1:FM_I2S_44K:44100,2:FM_I2S_48K:48000,3:error */
391 } fm_i2s_info_t;
392 
393 typedef enum {
394     FM_AUD_ANALOG = 0,
395     FM_AUD_I2S = 1,
396     FM_AUD_MRGIF = 2,
397     FM_AUD_ERR
398 } fm_audio_path_e;
399 
400 typedef enum {
401     FM_I2S_PAD_CONN = 0,
402     FM_I2S_PAD_IO = 1,
403     FM_I2S_PAD_ERR
404 } fm_i2s_pad_sel_e;
405 
406 typedef struct fm_audio_info {
407     fm_audio_path_e aud_path;
408     fm_i2s_info_t i2s_info;
409     fm_i2s_pad_sel_e i2s_pad;
410 } fm_audio_info_t;
411 
412 struct fm_cqi {
413     int ch;
414     int rssi;
415     int reserve;
416 };
417 
418 struct fm_cqi_req {
419     uint16_t ch_num;
420     int buf_size;
421     char *cqi_buf;
422 };
423 
424 typedef struct {
425     int freq;
426     int rssi;
427 } fm_desense_check_t;
428 
429 typedef struct {
430     uint16_t lower; // lower band, Eg, 7600 -> 76.0Mhz
431     uint16_t upper; // upper band, Eg, 10800 -> 108.0Mhz
432     int space; // 0x1: 50KHz, 0x2: 100Khz, 0x4: 200Khz
433     int cycle; // repeat times
434 } fm_full_cqi_log_t;
435 
436 // ********** ***********FM IOCTL define start *******************************
437 #define FM_IOC_MAGIC        0xf5
438 
439 #define FM_IOCTL_POWERUP       _IOWR(FM_IOC_MAGIC, 0, struct fm_tune_parm*)
440 #define FM_IOCTL_POWERDOWN     _IOWR(FM_IOC_MAGIC, 1, int32_t*)
441 #define FM_IOCTL_TUNE          _IOWR(FM_IOC_MAGIC, 2, struct fm_tune_parm*)
442 #define FM_IOCTL_SEEK          _IOWR(FM_IOC_MAGIC, 3, struct fm_seek_parm*)
443 #define FM_IOCTL_SETVOL        _IOWR(FM_IOC_MAGIC, 4, uint32_t*)
444 #define FM_IOCTL_GETVOL        _IOWR(FM_IOC_MAGIC, 5, uint32_t*)
445 #define FM_IOCTL_MUTE          _IOWR(FM_IOC_MAGIC, 6, uint32_t*)
446 #define FM_IOCTL_GETRSSI       _IOWR(FM_IOC_MAGIC, 7, int32_t*)
447 #define FM_IOCTL_SCAN          _IOWR(FM_IOC_MAGIC, 8, struct fm_scan_parm*)
448 #define FM_IOCTL_STOP_SCAN     _IO(FM_IOC_MAGIC,   9)
449 
450 //IOCTL and struct for test
451 #define FM_IOCTL_GETCHIPID     _IOWR(FM_IOC_MAGIC, 10, uint16_t*)
452 #define FM_IOCTL_EM_TEST       _IOWR(FM_IOC_MAGIC, 11, struct fm_em_parm*)
453 #define FM_IOCTL_RW_REG        _IOWR(FM_IOC_MAGIC, 12, struct fm_ctl_parm*)
454 #define FM_IOCTL_GETMONOSTERO  _IOWR(FM_IOC_MAGIC, 13, uint16_t*)
455 #define FM_IOCTL_GETCURPAMD    _IOWR(FM_IOC_MAGIC, 14, uint16_t*)
456 #define FM_IOCTL_GETGOODBCNT   _IOWR(FM_IOC_MAGIC, 15, uint16_t*)
457 #define FM_IOCTL_GETBADBNT     _IOWR(FM_IOC_MAGIC, 16, uint16_t*)
458 #define FM_IOCTL_GETBLERRATIO  _IOWR(FM_IOC_MAGIC, 17, uint16_t*)
459 
460 //IOCTL for RDS
461 #define FM_IOCTL_RDS_ONOFF     _IOWR(FM_IOC_MAGIC, 18, uint16_t*)
462 #define FM_IOCTL_RDS_SUPPORT   _IOWR(FM_IOC_MAGIC, 19, int32_t*)
463 
464 #define FM_IOCTL_RDS_SIM_DATA  _IOWR(FM_IOC_MAGIC, 23, uint32_t*)
465 #define FM_IOCTL_IS_FM_POWERED_UP  _IOWR(FM_IOC_MAGIC, 24, uint32_t*)
466 
467 //IOCTL for FM over BT
468 #define FM_IOCTL_OVER_BT_ENABLE  _IOWR(FM_IOC_MAGIC, 29, int32_t*)
469 
470 //IOCTL for FM ANTENNA SWITCH
471 #define FM_IOCTL_ANA_SWITCH     _IOWR(FM_IOC_MAGIC, 30, int32_t*)
472 #define FM_IOCTL_GETCAPARRAY      _IOWR(FM_IOC_MAGIC, 31, int32_t*)
473 
474 //IOCTL for FM I2S Setting
475 #define FM_IOCTL_I2S_SETTING  _IOWR(FM_IOC_MAGIC, 33, struct fm_i2s_setting*)
476 
477 #define FM_IOCTL_RDS_GROUPCNT   _IOWR(FM_IOC_MAGIC, 34, struct rds_group_cnt_req*)
478 #define FM_IOCTL_RDS_GET_LOG    _IOWR(FM_IOC_MAGIC, 35, struct rds_raw_data*)
479 
480 #define FM_IOCTL_SCAN_GETRSSI   _IOWR(FM_IOC_MAGIC, 36, struct fm_rssi_req*)
481 #define FM_IOCTL_SETMONOSTERO   _IOWR(FM_IOC_MAGIC, 37, int32_t)
482 #define FM_IOCTL_RDS_BC_RST     _IOWR(FM_IOC_MAGIC, 38, int32_t*)
483 #define FM_IOCTL_CQI_GET     _IOWR(FM_IOC_MAGIC, 39, struct fm_cqi_req*)
484 #define FM_IOCTL_GET_HW_INFO    _IOWR(FM_IOC_MAGIC, 40, struct fm_hw_info*)
485 #define FM_IOCTL_GET_I2S_INFO   _IOWR(FM_IOC_MAGIC, 41, fm_i2s_info_t*)
486 #define FM_IOCTL_IS_DESE_CHAN   _IOWR(FM_IOC_MAGIC, 42, int32_t*)
487 #define FM_IOCTL_TOP_RDWR _IOWR(FM_IOC_MAGIC, 43, struct fm_top_rw_parm*)
488 #define FM_IOCTL_HOST_RDWR  _IOWR(FM_IOC_MAGIC, 44, struct fm_host_rw_parm*)
489 
490 #define FM_IOCTL_PRE_SEARCH _IOWR(FM_IOC_MAGIC, 45,int32_t)
491 #define FM_IOCTL_RESTORE_SEARCH _IOWR(FM_IOC_MAGIC, 46,int32_t)
492 
493 #define FM_IOCTL_SET_SEARCH_THRESHOLD   _IOWR(FM_IOC_MAGIC, 47, fm_search_threshold_t*)
494 
495 #define FM_IOCTL_GET_AUDIO_INFO _IOWR(FM_IOC_MAGIC, 48, fm_audio_info_t*)
496 
497 #define FM_IOCTL_SCAN_NEW       _IOWR(FM_IOC_MAGIC, 60, struct fm_scan_t*)
498 #define FM_IOCTL_SEEK_NEW       _IOWR(FM_IOC_MAGIC, 61, struct fm_seek_t*)
499 #define FM_IOCTL_TUNE_NEW       _IOWR(FM_IOC_MAGIC, 62, struct fm_tune_t*)
500 
501 #define FM_IOCTL_SOFT_MUTE_TUNE _IOWR(FM_IOC_MAGIC, 63, struct fm_softmute_tune_t*)/*for soft mute tune*/
502 #define FM_IOCTL_DESENSE_CHECK   _IOWR(FM_IOC_MAGIC, 64, fm_desense_check_t*)
503 
504 //IOCTL for EM
505 #define FM_IOCTL_FULL_CQI_LOG _IOWR(FM_IOC_MAGIC, 70, fm_full_cqi_log_t *)
506 
507 #define FM_IOCTL_DUMP_REG   _IO(FM_IOC_MAGIC, 0xFF)
508 
509 // ********** ***********FM IOCTL define end *******************************
510 
511 enum group_idx {
512     mono = 0,
513     stereo,
514     RSSI_threshold,
515     HCC_Enable,
516     PAMD_threshold,
517     Softmute_Enable,
518     De_emphasis,
519     HL_Side,
520     Demod_BW,
521     Dynamic_Limiter,
522     Softmute_Rate,
523     AFC_Enable,
524     Softmute_Level,
525     Analog_Volume,
526     GROUP_TOTAL_NUMS
527 };
528 
529 enum item_idx {
530     Sblend_OFF = 0,
531     Sblend_ON,
532     ITEM_TOTAL_NUMS
533 };
534 
535 struct fm_ctl_parm {
536     uint8_t err;
537     uint8_t addr;
538     uint16_t val;
539     uint16_t rw_flag; // 0:write, 1:read
540 };
541 
542 struct fm_em_parm {
543     uint16_t group_idx;
544     uint16_t item_idx;
545     uint32_t item_value;
546 };
547 #endif // __FM_H__
548