MT6620: add the new driver JB2 V1.0
[firefly-linux-kernel-4.4.55.git] / drivers / mtk_wcn_combo / drv_fm / mt6626 / pub / mt6626_fm_cmd.c
1 #include <linux/kernel.h>
2
3 #include "fm_typedef.h"
4 #include "fm_dbg.h"
5 #include "fm_err.h"
6 #include "fm_rds.h"
7 #include "fm_cust_cfg.h"
8
9 #include "mt6626_fm_reg.h"
10 #include "mt6626_fm_link.h"
11 #include "mt6626_fm.h"
12 #include "mt6626_fm_cmd.h"
13
14 static fm_s32 fm_bop_write(fm_u8 addr, fm_u16 value, fm_u8 *buf, fm_s32 size)
15 {
16     if (size < (FM_WRITE_BASIC_OP_SIZE + 2)) {
17         return (-1);
18     }
19
20     if (buf == NULL) {
21         return (-2);
22     }
23
24     buf[0] = FM_WRITE_BASIC_OP;
25     buf[1] = FM_WRITE_BASIC_OP_SIZE;
26     buf[2] = addr;
27     buf[3] = (fm_u8)((value) & 0x00FF);
28     buf[4] = (fm_u8)((value >> 8) & 0x00FF);
29
30     WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4]);
31
32     return (FM_WRITE_BASIC_OP_SIZE + 2);
33 }
34
35 static fm_s32 fm_bop_udelay(fm_u32 value, fm_u8 *buf, fm_s32 size)
36 {
37     if (size < (FM_UDELAY_BASIC_OP_SIZE + 2)) {
38         return (-1);
39     }
40
41     if (buf == NULL) {
42         return (-2);
43     }
44
45     buf[0] = FM_UDELAY_BASIC_OP;
46     buf[1] = FM_UDELAY_BASIC_OP_SIZE;
47     buf[2] = (fm_u8)((value) & 0x000000FF);
48     buf[3] = (fm_u8)((value >> 8) & 0x000000FF);
49     buf[4] = (fm_u8)((value >> 16) & 0x000000FF);
50     buf[5] = (fm_u8)((value >> 24) & 0x000000FF);
51
52     WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
53
54     return (FM_UDELAY_BASIC_OP_SIZE + 2);
55 }
56
57 static fm_s32 fm_bop_rd_until(fm_u8 addr, fm_u16 mask, fm_u16 value, fm_u8 *buf, fm_s32 size)
58 {
59     if (size < (FM_RD_UNTIL_BASIC_OP_SIZE + 2)) {
60         return (-1);
61     }
62
63     if (buf == NULL) {
64         return (-2);
65     }
66
67     buf[0] = FM_RD_UNTIL_BASIC_OP;
68     buf[1] = FM_RD_UNTIL_BASIC_OP_SIZE;
69     buf[2] = addr;
70     buf[3] = (fm_u8)((mask) & 0x00FF);
71     buf[4] = (fm_u8)((mask >> 8) & 0x00FF);
72     buf[5] = (fm_u8)((value) & 0x00FF);
73     buf[6] = (fm_u8)((value >> 8) & 0x00FF);
74
75     WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
76
77     return (FM_RD_UNTIL_BASIC_OP_SIZE + 2);
78 }
79
80 static fm_s32 fm_bop_modify(fm_u8 addr, fm_u16 mask_and, fm_u16 mask_or, fm_u8 *buf, fm_s32 size)
81 {
82     if (size < (FM_MODIFY_BASIC_OP_SIZE + 2)) {
83         return (-1);
84     }
85
86     if (buf == NULL) {
87         return (-2);
88     }
89
90     buf[0] = FM_MODIFY_BASIC_OP;
91     buf[1] = FM_MODIFY_BASIC_OP_SIZE;
92     buf[2] = addr;
93     buf[3] = (fm_u8)((mask_and) & 0x00FF);
94     buf[4] = (fm_u8)((mask_and >> 8) & 0x00FF);
95     buf[5] = (fm_u8)((mask_or) & 0x00FF);
96     buf[6] = (fm_u8)((mask_or >> 8) & 0x00FF);
97
98     WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
99
100     return (FM_MODIFY_BASIC_OP_SIZE + 2);
101 }
102
103 #if 0
104 static fm_s32 fm_bop_msleep(fm_u32 value, fm_u8 *buf, fm_s32 size)
105 {
106     if (size < (FM_MSLEEP_BASIC_OP_SIZE + 2)) {
107         return (-1);
108     }
109
110     if (buf == NULL) {
111         return (-2);
112     }
113
114     buf[0] = FM_MSLEEP_BASIC_OP;
115     buf[1] = FM_MSLEEP_BASIC_OP_SIZE;
116     buf[2] = (fm_u8)((value) & 0x000000FF);
117     buf[3] = (fm_u8)((value >> 8) & 0x000000FF);
118     buf[4] = (fm_u8)((value >> 16) & 0x000000FF);
119     buf[5] = (fm_u8)((value >> 24) & 0x000000FF);
120
121     WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
122
123     return (FM_MSLEEP_BASIC_OP_SIZE + 2);
124 }
125 #endif
126
127 /*
128  * mt6626_pwrup_clock_on - Wholechip FM Power Up: step 1, FM Digital Clock enable
129  * @buf - target buf
130  * @buf_size - buffer size
131  * return package size
132  */
133 fm_s32 mt6626_pwrup_clock_on(fm_u8 *buf, fm_s32 buf_size)
134 {
135     fm_s32 pkt_size = 0;
136
137     if (buf_size < TX_BUF_SIZE) {
138         return (-1);
139     }
140
141     buf[0] = FM_TASK_COMMAND_PKT_TYPE;
142     buf[1] = FM_ENABLE_OPCODE;
143     pkt_size = 4;
144
145     //FM Digital Clock enable
146     pkt_size += fm_bop_write(0x60, 0x3000, &buf[pkt_size], buf_size - pkt_size);//wr 60 3000
147     pkt_size += fm_bop_write(0x60, 0x3001, &buf[pkt_size], buf_size - pkt_size);//wr 60 3001
148     pkt_size += fm_bop_udelay(3000, &buf[pkt_size], buf_size - pkt_size);//delay 3ms
149     pkt_size += fm_bop_write(0x60, 0x3003, &buf[pkt_size], buf_size - pkt_size);//wr 60 3003
150     pkt_size += fm_bop_write(0x60, 0x3007, &buf[pkt_size], buf_size - pkt_size);//wr 60 3007
151     //no low power mode, analog line in, long antenna
152     pkt_size += fm_bop_modify(0x61, 0xFF63, 0x0000, &buf[pkt_size], buf_size - pkt_size);
153
154     buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
155     buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
156
157     return pkt_size;
158 }
159
160 /*
161  * mt6626_patch_download - Wholechip FM Power Up: step 3, download patch to f/w,
162  * @buf - target buf
163  * @buf_size - buffer size
164  * @seg_num - total segments that this patch divided into
165  * @seg_id - No. of Segments: segment that will now be sent
166  * @src - patch source buffer
167  * @seg_len - segment size: segment that will now be sent
168  * return package size
169  */
170 fm_s32 mt6626_patch_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len)
171 {
172     fm_s32 pkt_size = 0;
173     fm_u8 *dst = NULL;
174
175     if (buf_size < TX_BUF_SIZE) {
176         return (-1);
177     }
178
179     buf[0] = FM_TASK_COMMAND_PKT_TYPE;
180     buf[1] = FM_PATCH_DOWNLOAD_OPCODE;
181     pkt_size = 4;
182
183     buf[pkt_size++] = seg_num;
184     buf[pkt_size++] = seg_id;
185
186     if (seg_len > (buf_size - pkt_size)) {
187         return -1;
188     }
189
190     dst = &buf[pkt_size];
191     pkt_size += seg_len;
192
193     //copy patch to tx buffer
194     while (seg_len--) {
195         *dst = *src;
196         //printk(KERN_ALERT "%02x ", *dst);
197         src++;
198         dst++;
199     }
200
201     buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
202     buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
203     WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
204
205     return pkt_size;
206 }
207
208 /*
209  * mt6626_coeff_download - Wholechip FM Power Up: step 3,download coeff to f/w,
210  * @buf - target buf
211  * @buf_size - buffer size
212  * @seg_num - total segments that this patch divided into
213  * @seg_id - No. of Segments: segment that will now be sent
214  * @src - patch source buffer
215  * @seg_len - segment size: segment that will now be sent
216  * return package size
217  */
218 fm_s32 mt6626_coeff_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len)
219 {
220     fm_s32 pkt_size = 0;
221     fm_u8 *dst = NULL;
222
223     if (buf_size < TX_BUF_SIZE) {
224         return (-1);
225     }
226
227     buf[0] = FM_TASK_COMMAND_PKT_TYPE;
228     buf[1] = FM_COEFF_DOWNLOAD_OPCODE;
229     pkt_size = 4;
230
231     buf[pkt_size++] = seg_num;
232     buf[pkt_size++] = seg_id;
233
234     if (seg_len > (buf_size - pkt_size)) {
235         return -1;
236     }
237
238     dst = &buf[pkt_size];
239     pkt_size += seg_len;
240
241     //copy patch to tx buffer
242     while (seg_len--) {
243         *dst = *src;
244         //printk(KERN_ALERT "%02x ", *dst);
245         src++;
246         dst++;
247     }
248
249     buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
250     buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
251     WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
252
253     return pkt_size;
254 }
255
256 /*
257  * mt6626_hwcoeff_download - Wholechip FM Power Up: step 3,download hwcoeff to f/w,
258  * @buf - target buf
259  * @buf_size - buffer size
260  * @seg_num - total segments that this patch divided into
261  * @seg_id - No. of Segments: segment that will now be sent
262  * @src - patch source buffer
263  * @seg_len - segment size: segment that will now be sent
264  * return package size
265  */
266 fm_s32 mt6626_hwcoeff_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len)
267 {
268     fm_s32 pkt_size = 0;
269     fm_u8 *dst = NULL;
270
271     if (buf_size < TX_BUF_SIZE) {
272         return (-1);
273     }
274
275     buf[0] = FM_TASK_COMMAND_PKT_TYPE;
276     buf[1] = FM_HWCOEFF_DOWNLOAD_OPCODE;
277     pkt_size = 4;
278
279     buf[pkt_size++] = seg_num;
280     buf[pkt_size++] = seg_id;
281
282     if (seg_len > (buf_size - pkt_size)) {
283         return -1;
284     }
285
286     dst = &buf[pkt_size];
287     pkt_size += seg_len;
288
289     //copy patch to tx buffer
290     while (seg_len--) {
291         *dst = *src;
292         //printk(KERN_ALERT "%02x ", *dst);
293         src++;
294         dst++;
295     }
296
297     buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
298     buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
299     WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
300
301     return pkt_size;
302 }
303
304 /*
305  * mt6626_rom_download - Wholechip FM Power Up: step 3,download rom to f/w,
306  * @buf - target buf
307  * @buf_size - buffer size
308  * @seg_num - total segments that this patch divided into
309  * @seg_id - No. of Segments: segment that will now be sent
310  * @src - patch source buffer
311  * @seg_len - segment size: segment that will now be sent
312  * return package size
313  */
314 fm_s32 mt6626_rom_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len)
315 {
316     fm_s32 pkt_size = 0;
317     fm_u8 *dst = NULL;
318
319     if (buf_size < TX_BUF_SIZE) {
320         return (-1);
321     }
322
323     buf[0] = FM_TASK_COMMAND_PKT_TYPE;
324     buf[1] = FM_ROM_DOWNLOAD_OPCODE;
325     pkt_size = 4;
326
327     buf[pkt_size++] = seg_num;
328     buf[pkt_size++] = seg_id;
329
330     if (seg_len > (buf_size - pkt_size)) {
331         return -1;
332     }
333
334     dst = &buf[pkt_size];
335     pkt_size += seg_len;
336
337     //copy patch to tx buffer
338     while (seg_len--) {
339         *dst = *src;
340         //printk(KERN_ALERT "%02x ", *dst);
341         src++;
342         dst++;
343     }
344
345     buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
346     buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
347     WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
348
349     return pkt_size;
350 }
351
352 /*
353  * mt6626_pwrup_digital_init - Wholechip FM Power Up: step 4, FM Digital Init: fm_rgf_maincon
354  * @buf - target buf
355  * @buf_size - buffer size
356  * return package size
357  */
358 fm_s32 mt6626_pwrup_digital_init_1(fm_u8 *buf, fm_s32 buf_size)
359 {
360     fm_s32 pkt_size = 0;
361
362     if (buf_size < TX_BUF_SIZE) {
363         return (-1);
364     }
365
366     buf[0] = FM_TASK_COMMAND_PKT_TYPE;
367     buf[1] = FM_ENABLE_OPCODE;
368     pkt_size = 4;
369
370     //Wholechip FM Power Up: FM Digital Init: fm_rgf_maincon
371     pkt_size += fm_bop_write(0x6A, 0x0020, &buf[pkt_size], buf_size - pkt_size);//wr 6A 0020
372     pkt_size += fm_bop_write(0x6B, 0x0020, &buf[pkt_size], buf_size - pkt_size);//wr 6B 0020
373     pkt_size += fm_bop_write(0xA0, 0xD0B1, &buf[pkt_size], buf_size - pkt_size);//wr a0 D0B1
374     pkt_size += fm_bop_write(0x60, 0x300F, &buf[pkt_size], buf_size - pkt_size);//wr 60 300F
375     pkt_size += fm_bop_write(0x61, 0x0003, &buf[pkt_size], buf_size - pkt_size);//wr 61 3
376     pkt_size += fm_bop_write(0x61, 0x0002, &buf[pkt_size], buf_size - pkt_size);//wr 61 2
377     //pkt_size += fm_bop_modify(0x61, 0xFFFF, 0x0002, &buf[pkt_size], buf_size - pkt_size);
378     //pkt_size += fm_bop_modify(0x61, 0xFFFE, 0x0000, &buf[pkt_size], buf_size - pkt_size);
379
380     buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
381     buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
382
383     return pkt_size;
384 }
385
386 /*
387  * mt6626_pwrup_digital_init - Wholechip FM Power Up: step 4, FM Digital Init: fm_rgf_maincon
388  * @buf - target buf
389  * @buf_size - buffer size
390  * return package size
391  */
392 fm_s32 mt6626_pwrup_digital_init_2(fm_u8 *buf, fm_s32 buf_size)
393 {
394     fm_s32 pkt_size = 0;
395
396     if (buf_size < TX_BUF_SIZE) {
397         return (-1);
398     }
399
400     buf[0] = FM_TASK_COMMAND_PKT_TYPE;
401     buf[1] = FM_ENABLE_OPCODE;
402     pkt_size = 4;
403
404     pkt_size += fm_bop_rd_until(0x64, 0x001F, 0x0002, &buf[pkt_size], buf_size - pkt_size);//Poll 64[0~4] = 2
405
406     buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
407     buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
408
409     return pkt_size;
410 }
411
412 /*
413  * mt6626_pwrdown - Wholechip FM Power down: Digital Modem Power Down
414  * @buf - target buf
415  * @buf_size - buffer size
416  * return package size
417  */
418 fm_s32 mt6626_pwrdown(fm_u8 *buf, fm_s32 buf_size)
419 {
420     fm_s32 pkt_size = 0;
421
422     if (buf_size < TX_BUF_SIZE) {
423         return (-1);
424     }
425
426     buf[0] = FM_TASK_COMMAND_PKT_TYPE;
427     buf[1] = FM_ENABLE_OPCODE;
428     pkt_size = 4;
429
430     //Disable HW clock control
431     pkt_size += fm_bop_write(0x60, 0x330F, &buf[pkt_size], buf_size - pkt_size);//wr 60 330F
432     //Reset ASIP
433     pkt_size += fm_bop_write(0x61, 0x0001, &buf[pkt_size], buf_size - pkt_size);//wr 61 0001
434     //digital core + digital rgf reset
435     pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 6E[0~2] 0
436     pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 6E[0~2] 0
437     pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 6E[0~2] 0
438     //Disable all clock
439     pkt_size += fm_bop_write(0x60, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 60 0000
440     //Reset rgfrf
441     pkt_size += fm_bop_write(0x60, 0x4000, &buf[pkt_size], buf_size - pkt_size);//wr 60 4000
442     pkt_size += fm_bop_write(0x60, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 60 0000
443
444     buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
445     buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
446
447     return pkt_size;
448 }
449
450 /*
451  * mt6626_rampdown - f/w will wait for STC_DONE interrupt
452  * @buf - target buf
453  * @buf_size - buffer size
454  * return package size
455  */
456 fm_s32 mt6626_rampdown(fm_u8 *buf, fm_s32 buf_size)
457 {
458     fm_s32 pkt_size = 0;
459
460     if (buf_size < TX_BUF_SIZE) {
461         return (-1);
462     }
463
464     buf[0] = FM_TASK_COMMAND_PKT_TYPE;
465     buf[1] = FM_RAMPDOWN_OPCODE;
466     pkt_size = 4;
467
468     //Clear DSP state
469     pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFF0, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 63[3:0] = 0
470     //Set DSP ramp down state
471     pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFFF, RAMP_DOWN, &buf[pkt_size], buf_size - pkt_size);//wr 63[8] = 1
472     //@Wait for STC_DONE interrupt@
473     pkt_size += fm_bop_rd_until(FM_MAIN_INTR, FM_INTR_STC_DONE, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//Poll 69[0] = b'1
474     //Clear DSP ramp down state
475     pkt_size += fm_bop_modify(FM_MAIN_CTRL, (~RAMP_DOWN), 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 63[8] = 0
476     //Write 1 clear the STC_DONE interrupt status flag
477     pkt_size += fm_bop_modify(FM_MAIN_INTR, 0xFFFF, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//wr 69[0] = 1
478
479     buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
480     buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
481
482     return pkt_size;
483 }
484
485 /*
486  * mt6626_tune - execute tune action,
487  * @buf - target buf
488  * @buf_size - buffer size
489  * @freq - 760 ~ 1080, 100KHz unit
490  * return package size
491  */
492 fm_s32 mt6626_tune(fm_u8 *buf, fm_s32 buf_size, fm_u16 freq)
493 {
494     fm_s32 pkt_size = 0;
495
496     if (buf_size < TX_BUF_SIZE) {
497         return (-1);
498     }
499
500     freq = (freq - 640) * 2;
501
502     buf[0] = FM_TASK_COMMAND_PKT_TYPE;
503     buf[1] = FM_TUNE_OPCODE;
504     pkt_size = 4;
505
506     //Set desired channel & channel parameter
507     pkt_size += fm_bop_modify(FM_CHANNEL_SET, 0xFC00, freq, &buf[pkt_size], buf_size - pkt_size);// set 0x65[9:0] = 0x029e, => ((97.5 - 64) * 20)
508     //Enable hardware controlled tuning sequence
509     pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFFE, TUNE, &buf[pkt_size], buf_size - pkt_size);// set 0x63[0] = 1
510     //Wait for STC_DONE interrupt
511     pkt_size += fm_bop_rd_until(FM_MAIN_INTR, FM_INTR_STC_DONE, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//Poll 69[0] = b'1
512     //Write 1 clear the STC_DONE interrupt status flag
513     pkt_size += fm_bop_modify(FM_MAIN_INTR, 0xFFFF, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//wr 69[0] = 1
514
515     buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
516     buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
517
518     return pkt_size;
519 }
520
521 /*
522  * mt6626_seek - execute seek action,
523  * @buf - target buf
524  * @buf_size - buffer size
525  * @seekdir - 0=seek up, 1=seek down
526  * @space - step, 50KHz:001, 100KHz:010, 200KHz:100
527  * @max_freq - upper bound
528  * @min_freq - lower bound
529  * return package size
530  */
531 fm_s32 mt6626_seek(fm_u8 *buf, fm_s32 buf_size, fm_u16 seekdir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq)
532 {
533     fm_s32 pkt_size = 0;
534
535     if (buf_size < TX_BUF_SIZE) {
536         return (-1);
537     }
538
539     buf[0] = FM_TASK_COMMAND_PKT_TYPE;
540     buf[1] = FM_SEEK_OPCODE;
541     pkt_size = 4;
542
543     //Program seek direction
544     if (seekdir == 0) {
545         pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFBFF, 0x0000, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 0, seek up
546     } else {
547         pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFFFF, 0x0400, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 1, seek down
548     }
549
550     //Program scan channel spacing
551     if (space == 1) {
552         pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x1000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=001
553     } else if (space == 2) {
554         pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x2000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=010
555     } else if (space == 4) {
556         pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x4000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=100
557     }
558
559     //enable wrap , if it is not auto scan function, 0x66[11] 0=no wrarp, 1=wrap
560     pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFFFF, 0x0800, &buf[pkt_size], buf_size - pkt_size);//0x66[11] = 1, wrap
561     //0x66[9:0] freq upper bound
562     max_freq = (max_freq - 640) * 2;
563     pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFC00, max_freq, &buf[pkt_size], buf_size - pkt_size);
564     //0x67[9:0] freq lower bound
565     min_freq = (min_freq - 640) * 2;
566     pkt_size += fm_bop_modify(FM_MAIN_CFG2, 0xFC00, min_freq, &buf[pkt_size], buf_size - pkt_size);
567     //Enable hardware controlled seeking sequence
568     pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFFF, SEEK, &buf[pkt_size], buf_size - pkt_size);//0x63[1] = 1
569     //Wait for STC_DONE interrupt
570     pkt_size += fm_bop_rd_until(FM_MAIN_INTR, FM_INTR_STC_DONE, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//Poll 69[0] = b'1
571     //Write 1 clear the STC_DONE interrupt status flag
572     pkt_size += fm_bop_modify(FM_MAIN_INTR, 0xFFFF, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//wr 69[0] = 1
573
574     buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
575     buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
576
577     return pkt_size;
578 }
579
580 /*
581  * mt6626_scan - execute scan action,
582  * @buf - target buf
583  * @buf_size - buffer size
584  * @scandir - 0=seek up, 1=seek down
585  * @space - step, 50KHz:001, 100KHz:010, 200KHz:100
586  * @max_freq - upper bound
587  * @min_freq - lower bound
588  * return package size
589  */
590 fm_s32 mt6626_scan(fm_u8 *buf, fm_s32 buf_size, fm_u16 scandir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq)
591 {
592     fm_s32 pkt_size = 0;
593
594     if (buf_size < TX_BUF_SIZE) {
595         return (-1);
596     }
597
598     buf[0] = FM_TASK_COMMAND_PKT_TYPE;
599     buf[1] = FM_SCAN_OPCODE;
600     pkt_size = 4;
601
602     //Program seek direction
603     if (scandir == 0) {
604         pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFBFF, 0x0000, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 0, seek up
605     } else {
606         pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFFFF, 0x0400, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 1, seek down
607     }
608
609     //Program scan channel spacing
610     if (space == 1) {
611         pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x1000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=001
612     } else if (space == 2) {
613         pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x2000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=010
614     } else if (space == 4) {
615         pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x4000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=100
616     }
617
618     //disable wrap , if it is auto scan function, 0x66[11] 0=no wrarp, 1=wrap
619     pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xF7FF, 0x0000, &buf[pkt_size], buf_size - pkt_size);//0x66[11] = 0, no wrap
620     //0x66[9:0] freq upper bound
621     max_freq = (max_freq - 640) * 2;
622     pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFC00, max_freq, &buf[pkt_size], buf_size - pkt_size);
623     //0x67[9:0] freq lower bound
624     min_freq = (min_freq - 640) * 2;
625     pkt_size += fm_bop_modify(FM_MAIN_CFG2, 0xFC00, min_freq, &buf[pkt_size], buf_size - pkt_size);
626     //Enable hardware controlled scanning sequence
627     pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFFF, SCAN, &buf[pkt_size], buf_size - pkt_size);//0x63[1] = 1
628     //Wait for STC_DONE interrupt
629     pkt_size += fm_bop_rd_until(FM_MAIN_INTR, FM_INTR_STC_DONE, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//Poll 69[0] = b'1
630     //Write 1 clear the STC_DONE interrupt status flag
631     pkt_size += fm_bop_modify(FM_MAIN_INTR, 0xFFFF, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//wr 69[0] = 1
632
633     buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
634     buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
635
636     return pkt_size;
637 }
638
639 fm_s32 mt6626_get_reg(fm_u8 *buf, fm_s32 buf_size, fm_u8 addr)
640 {
641     if (buf_size < TX_BUF_SIZE) {
642         return (-1);
643     }
644
645     buf[0] = FM_TASK_COMMAND_PKT_TYPE;
646     buf[1] = FSPI_READ_OPCODE;
647     buf[2] = 0x01;
648     buf[3] = 0x00;
649     buf[4] = addr;
650
651     WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4]);
652     return 5;
653 }
654
655 fm_s32 mt6626_set_reg(fm_u8 *buf, fm_s32 buf_size, fm_u8 addr, fm_u16 value)
656 {
657     if (buf_size < TX_BUF_SIZE) {
658         return (-1);
659     }
660
661     buf[0] = FM_TASK_COMMAND_PKT_TYPE;
662     buf[1] = FSPI_WRITE_OPCODE;
663     buf[2] = 0x03;
664     buf[3] = 0x00;
665     buf[4] = addr;
666     buf[5] = (fm_u8)((value) & 0x00FF);
667     buf[6] = (fm_u8)((value >> 8) & 0x00FF);
668
669     WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
670     return 7;
671 }
672