2 * cxd2880_tnrdmd_dvbt2.c
3 * Sony CXD2880 DVB-T2/T tuner + demodulator driver
4 * control functions for DVB-T2
6 * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; version 2 of the License.
12 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
13 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
15 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
16 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
17 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
18 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
21 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, see <http://www.gnu.org/licenses/>.
27 #include "cxd2880_tnrdmd_dvbt2.h"
28 #include "cxd2880_tnrdmd_dvbt2_mon.h"
30 static enum cxd2880_ret
x_tune_dvbt2_demod_setting(struct cxd2880_tnrdmd
32 enum cxd2880_dtv_bandwidth
34 enum cxd2880_tnrdmd_clockmode
38 return CXD2880_RESULT_ERROR_ARG
;
40 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
41 CXD2880_IO_TGT_SYS
, 0x00,
42 0x00) != CXD2880_RESULT_OK
)
43 return CXD2880_RESULT_ERROR_IO
;
45 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
46 CXD2880_IO_TGT_SYS
, 0x31,
47 0x02) != CXD2880_RESULT_OK
)
48 return CXD2880_RESULT_ERROR_IO
;
50 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
51 CXD2880_IO_TGT_DMD
, 0x00,
52 0x04) != CXD2880_RESULT_OK
)
53 return CXD2880_RESULT_ERROR_IO
;
55 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
56 CXD2880_IO_TGT_DMD
, 0x5D,
57 0x0B) != CXD2880_RESULT_OK
)
58 return CXD2880_RESULT_ERROR_IO
;
60 if (tnr_dmd
->diver_mode
!= CXD2880_TNRDMD_DIVERMODE_SUB
) {
61 u8 data
[2] = { 0x01, 0x01 };
63 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
64 CXD2880_IO_TGT_DMD
, 0x00,
65 0x00) != CXD2880_RESULT_OK
)
66 return CXD2880_RESULT_ERROR_IO
;
68 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
69 CXD2880_IO_TGT_DMD
, 0xCE, data
,
70 2) != CXD2880_RESULT_OK
)
71 return CXD2880_RESULT_ERROR_IO
;
75 u8 data
[14] = { 0x07, 0x06, 0x01, 0xF0,
76 0x00, 0x00, 0x04, 0xB0, 0x00, 0x00, 0x09, 0x9C, 0x0E,
80 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
81 CXD2880_IO_TGT_DMD
, 0x00,
82 0x20) != CXD2880_RESULT_OK
)
83 return CXD2880_RESULT_ERROR_IO
;
85 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
86 CXD2880_IO_TGT_DMD
, 0x8A,
87 data
[0]) != CXD2880_RESULT_OK
)
88 return CXD2880_RESULT_ERROR_IO
;
90 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
91 CXD2880_IO_TGT_DMD
, 0x90,
92 data
[1]) != CXD2880_RESULT_OK
)
93 return CXD2880_RESULT_ERROR_IO
;
95 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
96 CXD2880_IO_TGT_DMD
, 0x00,
97 0x25) != CXD2880_RESULT_OK
)
98 return CXD2880_RESULT_ERROR_IO
;
100 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
101 CXD2880_IO_TGT_DMD
, 0xF0, &data
[2],
102 2) != CXD2880_RESULT_OK
)
103 return CXD2880_RESULT_ERROR_IO
;
105 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
106 CXD2880_IO_TGT_DMD
, 0x00,
107 0x2A) != CXD2880_RESULT_OK
)
108 return CXD2880_RESULT_ERROR_IO
;
110 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
111 CXD2880_IO_TGT_DMD
, 0xDC,
112 data
[4]) != CXD2880_RESULT_OK
)
113 return CXD2880_RESULT_ERROR_IO
;
115 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
116 CXD2880_IO_TGT_DMD
, 0xDE,
117 data
[5]) != CXD2880_RESULT_OK
)
118 return CXD2880_RESULT_ERROR_IO
;
120 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
121 CXD2880_IO_TGT_DMD
, 0x00,
122 0x2D) != CXD2880_RESULT_OK
)
123 return CXD2880_RESULT_ERROR_IO
;
125 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
126 CXD2880_IO_TGT_DMD
, 0x73, &data
[6],
127 4) != CXD2880_RESULT_OK
)
128 return CXD2880_RESULT_ERROR_IO
;
130 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
131 CXD2880_IO_TGT_DMD
, 0x8F, &data
[10],
132 4) != CXD2880_RESULT_OK
)
133 return CXD2880_RESULT_ERROR_IO
;
137 u8 data_a_1
[9] = { 0x52, 0x49, 0x2C, 0x51,
138 0x51, 0x3D, 0x15, 0x29, 0x0C
140 u8 data_b_1
[9] = { 0x5D, 0x55, 0x32, 0x5C,
141 0x5C, 0x45, 0x17, 0x2E, 0x0D
143 u8 data_c_1
[9] = { 0x60, 0x00, 0x34, 0x5E,
144 0x5E, 0x47, 0x18, 0x2F, 0x0E
147 u8 data_a_2
[13] = { 0x04, 0xE7, 0x94, 0x92,
148 0x09, 0xCF, 0x7E, 0xD0, 0x49, 0xCD, 0xCD, 0x1F, 0x5B
150 u8 data_b_2
[13] = { 0x05, 0x90, 0x27, 0x55,
151 0x0B, 0x20, 0x8F, 0xD6, 0xEA, 0xC8, 0xC8, 0x23, 0x91
153 u8 data_c_2
[13] = { 0x05, 0xB8, 0xD8, 0x00,
154 0x0B, 0x72, 0x93, 0xF3, 0x00, 0xCD, 0xCD, 0x24, 0x95
157 u8 data_a_3
[5] = { 0x0B, 0x6A, 0xC9, 0x03,
160 u8 data_b_3
[5] = { 0x01, 0x02, 0xE4, 0x03,
163 u8 data_c_3
[5] = { 0x01, 0x02, 0xEB, 0x03,
172 case CXD2880_TNRDMD_CLOCKMODE_A
:
177 case CXD2880_TNRDMD_CLOCKMODE_B
:
182 case CXD2880_TNRDMD_CLOCKMODE_C
:
188 return CXD2880_RESULT_ERROR_SW_STATE
;
191 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
192 CXD2880_IO_TGT_DMD
, 0x00,
193 0x04) != CXD2880_RESULT_OK
)
194 return CXD2880_RESULT_ERROR_IO
;
196 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
197 CXD2880_IO_TGT_DMD
, 0x1D,
198 &data_1
[0], 3) != CXD2880_RESULT_OK
)
199 return CXD2880_RESULT_ERROR_IO
;
201 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
202 CXD2880_IO_TGT_DMD
, 0x22,
203 data_1
[3]) != CXD2880_RESULT_OK
)
204 return CXD2880_RESULT_ERROR_IO
;
206 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
207 CXD2880_IO_TGT_DMD
, 0x24,
208 data_1
[4]) != CXD2880_RESULT_OK
)
209 return CXD2880_RESULT_ERROR_IO
;
211 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
212 CXD2880_IO_TGT_DMD
, 0x26,
213 data_1
[5]) != CXD2880_RESULT_OK
)
214 return CXD2880_RESULT_ERROR_IO
;
216 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
217 CXD2880_IO_TGT_DMD
, 0x29,
218 &data_1
[6], 2) != CXD2880_RESULT_OK
)
219 return CXD2880_RESULT_ERROR_IO
;
221 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
222 CXD2880_IO_TGT_DMD
, 0x2D,
223 data_1
[8]) != CXD2880_RESULT_OK
)
224 return CXD2880_RESULT_ERROR_IO
;
226 if (tnr_dmd
->diver_mode
!= CXD2880_TNRDMD_DIVERMODE_SUB
) {
227 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
228 CXD2880_IO_TGT_DMD
, 0x2E,
230 6) != CXD2880_RESULT_OK
)
231 return CXD2880_RESULT_ERROR_IO
;
233 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
234 CXD2880_IO_TGT_DMD
, 0x35,
236 7) != CXD2880_RESULT_OK
)
237 return CXD2880_RESULT_ERROR_IO
;
240 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
241 CXD2880_IO_TGT_DMD
, 0x3C,
242 &data_3
[0], 2) != CXD2880_RESULT_OK
)
243 return CXD2880_RESULT_ERROR_IO
;
245 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
246 CXD2880_IO_TGT_DMD
, 0x56,
247 &data_3
[2], 3) != CXD2880_RESULT_OK
)
248 return CXD2880_RESULT_ERROR_IO
;
252 case CXD2880_DTV_BW_8_MHZ
:
255 u8 data_ac
[6] = { 0x15, 0x00, 0x00, 0x00,
258 u8 data_b
[6] = { 0x14, 0x6A, 0xAA, 0xAA,
264 case CXD2880_TNRDMD_CLOCKMODE_A
:
265 case CXD2880_TNRDMD_CLOCKMODE_C
:
268 case CXD2880_TNRDMD_CLOCKMODE_B
:
272 return CXD2880_RESULT_ERROR_SW_STATE
;
275 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
276 CXD2880_IO_TGT_DMD
, 0x10,
278 6) != CXD2880_RESULT_OK
)
279 return CXD2880_RESULT_ERROR_IO
;
282 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
283 CXD2880_IO_TGT_DMD
, 0x4A,
284 0x00) != CXD2880_RESULT_OK
)
285 return CXD2880_RESULT_ERROR_IO
;
288 u8 data_a
[2] = { 0x19, 0xD2 };
289 u8 data_bc
[2] = { 0x3F, 0xFF };
293 case CXD2880_TNRDMD_CLOCKMODE_A
:
296 case CXD2880_TNRDMD_CLOCKMODE_B
:
297 case CXD2880_TNRDMD_CLOCKMODE_C
:
301 return CXD2880_RESULT_ERROR_SW_STATE
;
304 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
305 CXD2880_IO_TGT_DMD
, 0x19,
307 2) != CXD2880_RESULT_OK
)
308 return CXD2880_RESULT_ERROR_IO
;
312 u8 data_a
[2] = { 0x06, 0x2A };
313 u8 data_b
[2] = { 0x06, 0x29 };
314 u8 data_c
[2] = { 0x06, 0x28 };
318 case CXD2880_TNRDMD_CLOCKMODE_A
:
321 case CXD2880_TNRDMD_CLOCKMODE_B
:
324 case CXD2880_TNRDMD_CLOCKMODE_C
:
328 return CXD2880_RESULT_ERROR_SW_STATE
;
331 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
332 CXD2880_IO_TGT_DMD
, 0x1B,
334 2) != CXD2880_RESULT_OK
)
335 return CXD2880_RESULT_ERROR_IO
;
338 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_MAIN
) {
339 u8 data_a
[9] = { 0x28, 0x00, 0x50, 0x00,
340 0x60, 0x00, 0x00, 0x90, 0x00
342 u8 data_b
[9] = { 0x2D, 0x5E, 0x5A, 0xBD,
343 0x6C, 0xE3, 0x00, 0xA3, 0x55
345 u8 data_c
[9] = { 0x2E, 0xAA, 0x5D, 0x55,
346 0x70, 0x00, 0x00, 0xA8, 0x00
351 case CXD2880_TNRDMD_CLOCKMODE_A
:
354 case CXD2880_TNRDMD_CLOCKMODE_B
:
357 case CXD2880_TNRDMD_CLOCKMODE_C
:
361 return CXD2880_RESULT_ERROR_SW_STATE
;
364 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
365 CXD2880_IO_TGT_DMD
, 0x4B,
367 9) != CXD2880_RESULT_OK
)
368 return CXD2880_RESULT_ERROR_IO
;
372 case CXD2880_DTV_BW_7_MHZ
:
375 u8 data_ac
[6] = { 0x18, 0x00, 0x00, 0x00,
378 u8 data_b
[6] = { 0x17, 0x55, 0x55, 0x55,
384 case CXD2880_TNRDMD_CLOCKMODE_A
:
385 case CXD2880_TNRDMD_CLOCKMODE_C
:
388 case CXD2880_TNRDMD_CLOCKMODE_B
:
392 return CXD2880_RESULT_ERROR_SW_STATE
;
395 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
396 CXD2880_IO_TGT_DMD
, 0x10,
398 6) != CXD2880_RESULT_OK
)
399 return CXD2880_RESULT_ERROR_IO
;
402 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
403 CXD2880_IO_TGT_DMD
, 0x4A,
404 0x02) != CXD2880_RESULT_OK
)
405 return CXD2880_RESULT_ERROR_IO
;
408 u8 data
[2] = { 0x3F, 0xFF };
410 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
411 CXD2880_IO_TGT_DMD
, 0x19,
413 2) != CXD2880_RESULT_OK
)
414 return CXD2880_RESULT_ERROR_IO
;
418 u8 data_a
[2] = { 0x06, 0x23 };
419 u8 data_b
[2] = { 0x06, 0x22 };
420 u8 data_c
[2] = { 0x06, 0x21 };
424 case CXD2880_TNRDMD_CLOCKMODE_A
:
427 case CXD2880_TNRDMD_CLOCKMODE_B
:
430 case CXD2880_TNRDMD_CLOCKMODE_C
:
434 return CXD2880_RESULT_ERROR_SW_STATE
;
437 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
438 CXD2880_IO_TGT_DMD
, 0x1B,
440 2) != CXD2880_RESULT_OK
)
441 return CXD2880_RESULT_ERROR_IO
;
444 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_MAIN
) {
445 u8 data_a
[9] = { 0x2D, 0xB6, 0x5B, 0x6D,
446 0x6D, 0xB6, 0x00, 0xA4, 0x92
448 u8 data_b
[9] = { 0x33, 0xDA, 0x67, 0xB4,
449 0x7C, 0x71, 0x00, 0xBA, 0xAA
451 u8 data_c
[9] = { 0x35, 0x55, 0x6A, 0xAA,
452 0x80, 0x00, 0x00, 0xC0, 0x00
457 case CXD2880_TNRDMD_CLOCKMODE_A
:
460 case CXD2880_TNRDMD_CLOCKMODE_B
:
463 case CXD2880_TNRDMD_CLOCKMODE_C
:
467 return CXD2880_RESULT_ERROR_SW_STATE
;
470 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
471 CXD2880_IO_TGT_DMD
, 0x4B,
473 9) != CXD2880_RESULT_OK
)
474 return CXD2880_RESULT_ERROR_IO
;
478 case CXD2880_DTV_BW_6_MHZ
:
481 u8 data_ac
[6] = { 0x1C, 0x00, 0x00, 0x00,
484 u8 data_b
[6] = { 0x1B, 0x38, 0xE3, 0x8E,
490 case CXD2880_TNRDMD_CLOCKMODE_A
:
491 case CXD2880_TNRDMD_CLOCKMODE_C
:
494 case CXD2880_TNRDMD_CLOCKMODE_B
:
498 return CXD2880_RESULT_ERROR_SW_STATE
;
501 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
502 CXD2880_IO_TGT_DMD
, 0x10,
504 6) != CXD2880_RESULT_OK
)
505 return CXD2880_RESULT_ERROR_IO
;
508 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
509 CXD2880_IO_TGT_DMD
, 0x4A,
510 0x04) != CXD2880_RESULT_OK
)
511 return CXD2880_RESULT_ERROR_IO
;
514 u8 data
[2] = { 0x3F, 0xFF };
516 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
517 CXD2880_IO_TGT_DMD
, 0x19,
519 2) != CXD2880_RESULT_OK
)
520 return CXD2880_RESULT_ERROR_IO
;
524 u8 data_a
[2] = { 0x06, 0x1C };
525 u8 data_b
[2] = { 0x06, 0x1B };
526 u8 data_c
[2] = { 0x06, 0x1A };
530 case CXD2880_TNRDMD_CLOCKMODE_A
:
533 case CXD2880_TNRDMD_CLOCKMODE_B
:
536 case CXD2880_TNRDMD_CLOCKMODE_C
:
540 return CXD2880_RESULT_ERROR_SW_STATE
;
543 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
544 CXD2880_IO_TGT_DMD
, 0x1B,
546 2) != CXD2880_RESULT_OK
)
547 return CXD2880_RESULT_ERROR_IO
;
550 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_MAIN
) {
551 u8 data_a
[9] = { 0x35, 0x55, 0x6A, 0xAA,
552 0x80, 0x00, 0x00, 0xC0, 0x00
554 u8 data_b
[9] = { 0x3C, 0x7E, 0x78, 0xFC,
555 0x91, 0x2F, 0x00, 0xD9, 0xC7
557 u8 data_c
[9] = { 0x3E, 0x38, 0x7C, 0x71,
558 0x95, 0x55, 0x00, 0xDF, 0xFF
563 case CXD2880_TNRDMD_CLOCKMODE_A
:
566 case CXD2880_TNRDMD_CLOCKMODE_B
:
569 case CXD2880_TNRDMD_CLOCKMODE_C
:
573 return CXD2880_RESULT_ERROR_SW_STATE
;
576 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
577 CXD2880_IO_TGT_DMD
, 0x4B,
579 9) != CXD2880_RESULT_OK
)
580 return CXD2880_RESULT_ERROR_IO
;
584 case CXD2880_DTV_BW_5_MHZ
:
587 u8 data_ac
[6] = { 0x21, 0x99, 0x99, 0x99,
590 u8 data_b
[6] = { 0x20, 0xAA, 0xAA, 0xAA,
596 case CXD2880_TNRDMD_CLOCKMODE_A
:
597 case CXD2880_TNRDMD_CLOCKMODE_C
:
600 case CXD2880_TNRDMD_CLOCKMODE_B
:
604 return CXD2880_RESULT_ERROR_SW_STATE
;
607 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
608 CXD2880_IO_TGT_DMD
, 0x10,
610 6) != CXD2880_RESULT_OK
)
611 return CXD2880_RESULT_ERROR_IO
;
614 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
615 CXD2880_IO_TGT_DMD
, 0x4A,
616 0x06) != CXD2880_RESULT_OK
)
617 return CXD2880_RESULT_ERROR_IO
;
620 u8 data
[2] = { 0x3F, 0xFF };
622 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
623 CXD2880_IO_TGT_DMD
, 0x19,
625 2) != CXD2880_RESULT_OK
)
626 return CXD2880_RESULT_ERROR_IO
;
630 u8 data_a
[2] = { 0x06, 0x15 };
631 u8 data_b
[2] = { 0x06, 0x15 };
632 u8 data_c
[2] = { 0x06, 0x14 };
636 case CXD2880_TNRDMD_CLOCKMODE_A
:
639 case CXD2880_TNRDMD_CLOCKMODE_B
:
642 case CXD2880_TNRDMD_CLOCKMODE_C
:
646 return CXD2880_RESULT_ERROR_SW_STATE
;
649 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
650 CXD2880_IO_TGT_DMD
, 0x1B,
652 2) != CXD2880_RESULT_OK
)
653 return CXD2880_RESULT_ERROR_IO
;
656 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_MAIN
) {
657 u8 data_a
[9] = { 0x40, 0x00, 0x6A, 0xAA,
658 0x80, 0x00, 0x00, 0xE6, 0x66
660 u8 data_b
[9] = { 0x48, 0x97, 0x78, 0xFC,
661 0x91, 0x2F, 0x01, 0x05, 0x55
663 u8 data_c
[9] = { 0x4A, 0xAA, 0x7C, 0x71,
664 0x95, 0x55, 0x01, 0x0C, 0xCC
669 case CXD2880_TNRDMD_CLOCKMODE_A
:
672 case CXD2880_TNRDMD_CLOCKMODE_B
:
675 case CXD2880_TNRDMD_CLOCKMODE_C
:
679 return CXD2880_RESULT_ERROR_SW_STATE
;
682 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
683 CXD2880_IO_TGT_DMD
, 0x4B,
685 9) != CXD2880_RESULT_OK
)
686 return CXD2880_RESULT_ERROR_IO
;
690 case CXD2880_DTV_BW_1_7_MHZ
:
693 u8 data_a
[6] = { 0x68, 0x0F, 0xA2, 0x32,
696 u8 data_c
[6] = { 0x68, 0x0F, 0xA2, 0x32,
699 u8 data_b
[6] = { 0x65, 0x2B, 0xA4, 0xCD,
705 case CXD2880_TNRDMD_CLOCKMODE_A
:
708 case CXD2880_TNRDMD_CLOCKMODE_C
:
711 case CXD2880_TNRDMD_CLOCKMODE_B
:
715 return CXD2880_RESULT_ERROR_SW_STATE
;
718 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
719 CXD2880_IO_TGT_DMD
, 0x10,
721 6) != CXD2880_RESULT_OK
)
722 return CXD2880_RESULT_ERROR_IO
;
725 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
726 CXD2880_IO_TGT_DMD
, 0x4A,
727 0x03) != CXD2880_RESULT_OK
)
728 return CXD2880_RESULT_ERROR_IO
;
731 u8 data
[2] = { 0x3F, 0xFF };
733 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
734 CXD2880_IO_TGT_DMD
, 0x19,
736 2) != CXD2880_RESULT_OK
)
737 return CXD2880_RESULT_ERROR_IO
;
741 u8 data_a
[2] = { 0x06, 0x0C };
742 u8 data_b
[2] = { 0x06, 0x0C };
743 u8 data_c
[2] = { 0x06, 0x0B };
747 case CXD2880_TNRDMD_CLOCKMODE_A
:
750 case CXD2880_TNRDMD_CLOCKMODE_B
:
753 case CXD2880_TNRDMD_CLOCKMODE_C
:
757 return CXD2880_RESULT_ERROR_SW_STATE
;
760 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
761 CXD2880_IO_TGT_DMD
, 0x1B,
763 2) != CXD2880_RESULT_OK
)
764 return CXD2880_RESULT_ERROR_IO
;
767 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_MAIN
) {
768 u8 data_a
[9] = { 0x40, 0x00, 0x6A, 0xAA,
769 0x80, 0x00, 0x02, 0xC9, 0x8F
771 u8 data_b
[9] = { 0x48, 0x97, 0x78, 0xFC,
772 0x91, 0x2F, 0x03, 0x29, 0x5D
774 u8 data_c
[9] = { 0x4A, 0xAA, 0x7C, 0x71,
775 0x95, 0x55, 0x03, 0x40, 0x7D
780 case CXD2880_TNRDMD_CLOCKMODE_A
:
783 case CXD2880_TNRDMD_CLOCKMODE_B
:
786 case CXD2880_TNRDMD_CLOCKMODE_C
:
790 return CXD2880_RESULT_ERROR_SW_STATE
;
793 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
794 CXD2880_IO_TGT_DMD
, 0x4B,
796 9) != CXD2880_RESULT_OK
)
797 return CXD2880_RESULT_ERROR_IO
;
802 return CXD2880_RESULT_ERROR_SW_STATE
;
805 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
806 CXD2880_IO_TGT_DMD
, 0x00,
807 0x00) != CXD2880_RESULT_OK
)
808 return CXD2880_RESULT_ERROR_IO
;
810 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
811 CXD2880_IO_TGT_DMD
, 0xFD,
812 0x01) != CXD2880_RESULT_OK
)
813 return CXD2880_RESULT_ERROR_IO
;
815 return CXD2880_RESULT_OK
;
818 static enum cxd2880_ret
x_sleep_dvbt2_demod_setting(struct cxd2880_tnrdmd
822 return CXD2880_RESULT_ERROR_ARG
;
824 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_MAIN
) {
825 u8 data
[] = { 0, 1, 0, 2,
826 0, 4, 0, 8, 0, 16, 0, 32
829 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
830 CXD2880_IO_TGT_DMD
, 0x00,
831 0x1D) != CXD2880_RESULT_OK
)
832 return CXD2880_RESULT_ERROR_IO
;
834 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
835 CXD2880_IO_TGT_DMD
, 0x47, data
,
836 12) != CXD2880_RESULT_OK
)
837 return CXD2880_RESULT_ERROR_IO
;
840 return CXD2880_RESULT_OK
;
843 static enum cxd2880_ret
dvbt2_set_profile(struct cxd2880_tnrdmd
*tnr_dmd
,
844 enum cxd2880_dvbt2_profile profile
)
846 u8 t2_mode_tune_mode
= 0;
847 u8 seq_not2_dtime
= 0;
848 enum cxd2880_ret ret
= CXD2880_RESULT_OK
;
851 return CXD2880_RESULT_ERROR_ARG
;
857 switch (tnr_dmd
->clk_mode
) {
858 case CXD2880_TNRDMD_CLOCKMODE_A
:
862 case CXD2880_TNRDMD_CLOCKMODE_B
:
866 case CXD2880_TNRDMD_CLOCKMODE_C
:
871 return CXD2880_RESULT_ERROR_SW_STATE
;
875 case CXD2880_DVBT2_PROFILE_BASE
:
876 t2_mode_tune_mode
= 0x01;
877 seq_not2_dtime
= dtime2
;
880 case CXD2880_DVBT2_PROFILE_LITE
:
881 t2_mode_tune_mode
= 0x05;
882 seq_not2_dtime
= dtime1
;
885 case CXD2880_DVBT2_PROFILE_ANY
:
886 t2_mode_tune_mode
= 0x00;
887 seq_not2_dtime
= dtime1
;
891 return CXD2880_RESULT_ERROR_ARG
;
895 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
896 CXD2880_IO_TGT_DMD
, 0x00,
897 0x2E) != CXD2880_RESULT_OK
)
898 return CXD2880_RESULT_ERROR_IO
;
900 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
901 CXD2880_IO_TGT_DMD
, 0x10,
902 t2_mode_tune_mode
) != CXD2880_RESULT_OK
)
903 return CXD2880_RESULT_ERROR_IO
;
905 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
906 CXD2880_IO_TGT_DMD
, 0x00,
907 0x04) != CXD2880_RESULT_OK
)
908 return CXD2880_RESULT_ERROR_IO
;
910 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
911 CXD2880_IO_TGT_DMD
, 0x2C,
912 seq_not2_dtime
) != CXD2880_RESULT_OK
)
913 return CXD2880_RESULT_ERROR_IO
;
918 enum cxd2880_ret
cxd2880_tnrdmd_dvbt2_tune1(struct cxd2880_tnrdmd
*tnr_dmd
,
919 struct cxd2880_dvbt2_tune_param
922 enum cxd2880_ret ret
= CXD2880_RESULT_OK
;
924 if ((!tnr_dmd
) || (!tune_param
))
925 return CXD2880_RESULT_ERROR_ARG
;
927 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_SUB
)
928 return CXD2880_RESULT_ERROR_ARG
;
930 if ((tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_SLEEP
) &&
931 (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
))
932 return CXD2880_RESULT_ERROR_SW_STATE
;
934 if ((tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_MAIN
) &&
935 (tune_param
->profile
== CXD2880_DVBT2_PROFILE_ANY
))
936 return CXD2880_RESULT_ERROR_NOSUPPORT
;
939 cxd2880_tnrdmd_common_tune_setting1(tnr_dmd
, CXD2880_DTV_SYS_DVBT2
,
940 tune_param
->center_freq_khz
,
941 tune_param
->bandwidth
, 0, 0);
942 if (ret
!= CXD2880_RESULT_OK
)
946 x_tune_dvbt2_demod_setting(tnr_dmd
, tune_param
->bandwidth
,
948 if (ret
!= CXD2880_RESULT_OK
)
951 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_MAIN
) {
953 x_tune_dvbt2_demod_setting(tnr_dmd
->diver_sub
,
954 tune_param
->bandwidth
,
955 tnr_dmd
->diver_sub
->clk_mode
);
956 if (ret
!= CXD2880_RESULT_OK
)
960 ret
= dvbt2_set_profile(tnr_dmd
, tune_param
->profile
);
961 if (ret
!= CXD2880_RESULT_OK
)
964 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_MAIN
) {
966 dvbt2_set_profile(tnr_dmd
->diver_sub
, tune_param
->profile
);
967 if (ret
!= CXD2880_RESULT_OK
)
971 if (tune_param
->data_plp_id
== CXD2880_DVBT2_TUNE_PARAM_PLPID_AUTO
) {
972 ret
= cxd2880_tnrdmd_dvbt2_set_plp_cfg(tnr_dmd
, 1, 0);
973 if (ret
!= CXD2880_RESULT_OK
)
977 cxd2880_tnrdmd_dvbt2_set_plp_cfg(tnr_dmd
, 0,
978 (u8
)(tune_param
->data_plp_id
));
979 if (ret
!= CXD2880_RESULT_OK
)
983 return CXD2880_RESULT_OK
;
986 enum cxd2880_ret
cxd2880_tnrdmd_dvbt2_tune2(struct cxd2880_tnrdmd
*tnr_dmd
,
987 struct cxd2880_dvbt2_tune_param
990 enum cxd2880_ret ret
= CXD2880_RESULT_OK
;
992 if ((!tnr_dmd
) || (!tune_param
))
993 return CXD2880_RESULT_ERROR_ARG
;
995 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_SUB
)
996 return CXD2880_RESULT_ERROR_ARG
;
998 if ((tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_SLEEP
) &&
999 (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
))
1000 return CXD2880_RESULT_ERROR_SW_STATE
;
1003 u8 en_fef_intmtnt_ctrl
= 1;
1005 switch (tune_param
->profile
) {
1006 case CXD2880_DVBT2_PROFILE_BASE
:
1007 en_fef_intmtnt_ctrl
= tnr_dmd
->en_fef_intmtnt_base
;
1009 case CXD2880_DVBT2_PROFILE_LITE
:
1010 en_fef_intmtnt_ctrl
= tnr_dmd
->en_fef_intmtnt_lite
;
1012 case CXD2880_DVBT2_PROFILE_ANY
:
1013 if (tnr_dmd
->en_fef_intmtnt_base
&&
1014 tnr_dmd
->en_fef_intmtnt_lite
)
1015 en_fef_intmtnt_ctrl
= 1;
1017 en_fef_intmtnt_ctrl
= 0;
1020 return CXD2880_RESULT_ERROR_ARG
;
1024 cxd2880_tnrdmd_common_tune_setting2(tnr_dmd
,
1025 CXD2880_DTV_SYS_DVBT2
,
1026 en_fef_intmtnt_ctrl
);
1027 if (ret
!= CXD2880_RESULT_OK
)
1031 tnr_dmd
->state
= CXD2880_TNRDMD_STATE_ACTIVE
;
1032 tnr_dmd
->frequency_khz
= tune_param
->center_freq_khz
;
1033 tnr_dmd
->sys
= CXD2880_DTV_SYS_DVBT2
;
1034 tnr_dmd
->bandwidth
= tune_param
->bandwidth
;
1036 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_MAIN
) {
1037 tnr_dmd
->diver_sub
->state
= CXD2880_TNRDMD_STATE_ACTIVE
;
1038 tnr_dmd
->diver_sub
->frequency_khz
= tune_param
->center_freq_khz
;
1039 tnr_dmd
->diver_sub
->sys
= CXD2880_DTV_SYS_DVBT2
;
1040 tnr_dmd
->diver_sub
->bandwidth
= tune_param
->bandwidth
;
1043 return CXD2880_RESULT_OK
;
1046 enum cxd2880_ret
cxd2880_tnrdmd_dvbt2_sleep_setting(struct cxd2880_tnrdmd
1049 enum cxd2880_ret ret
= CXD2880_RESULT_OK
;
1052 return CXD2880_RESULT_ERROR_ARG
;
1054 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_SUB
)
1055 return CXD2880_RESULT_ERROR_ARG
;
1057 if ((tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_SLEEP
) &&
1058 (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
))
1059 return CXD2880_RESULT_ERROR_SW_STATE
;
1061 ret
= x_sleep_dvbt2_demod_setting(tnr_dmd
);
1062 if (ret
!= CXD2880_RESULT_OK
)
1065 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_MAIN
) {
1066 ret
= x_sleep_dvbt2_demod_setting(tnr_dmd
->diver_sub
);
1067 if (ret
!= CXD2880_RESULT_OK
)
1071 return CXD2880_RESULT_OK
;
1074 enum cxd2880_ret
cxd2880_tnrdmd_dvbt2_check_demod_lock(struct cxd2880_tnrdmd
1077 cxd2880_tnrdmd_lock_result
1080 enum cxd2880_ret ret
= CXD2880_RESULT_OK
;
1084 u8 unlock_detected
= 0;
1085 u8 unlock_detected_sub
= 0;
1087 if ((!tnr_dmd
) || (!lock
))
1088 return CXD2880_RESULT_ERROR_ARG
;
1090 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_SUB
)
1091 return CXD2880_RESULT_ERROR_ARG
;
1093 if (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
)
1094 return CXD2880_RESULT_ERROR_SW_STATE
;
1097 cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd
, &sync_stat
, &ts_lock
,
1099 if (ret
!= CXD2880_RESULT_OK
)
1102 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_SINGLE
) {
1104 *lock
= CXD2880_TNRDMD_LOCK_RESULT_LOCKED
;
1105 else if (unlock_detected
)
1106 *lock
= CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED
;
1108 *lock
= CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT
;
1113 if (sync_stat
== 6) {
1114 *lock
= CXD2880_TNRDMD_LOCK_RESULT_LOCKED
;
1119 cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub(tnr_dmd
, &sync_stat
,
1120 &unlock_detected_sub
);
1121 if (ret
!= CXD2880_RESULT_OK
)
1125 *lock
= CXD2880_TNRDMD_LOCK_RESULT_LOCKED
;
1126 else if (unlock_detected
&& unlock_detected_sub
)
1127 *lock
= CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED
;
1129 *lock
= CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT
;
1134 enum cxd2880_ret
cxd2880_tnrdmd_dvbt2_check_ts_lock(struct cxd2880_tnrdmd
1137 cxd2880_tnrdmd_lock_result
1140 enum cxd2880_ret ret
= CXD2880_RESULT_OK
;
1144 u8 unlock_detected
= 0;
1145 u8 unlock_detected_sub
= 0;
1147 if ((!tnr_dmd
) || (!lock
))
1148 return CXD2880_RESULT_ERROR_ARG
;
1150 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_SUB
)
1151 return CXD2880_RESULT_ERROR_ARG
;
1153 if (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
)
1154 return CXD2880_RESULT_ERROR_SW_STATE
;
1157 cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd
, &sync_stat
, &ts_lock
,
1159 if (ret
!= CXD2880_RESULT_OK
)
1162 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_SINGLE
) {
1164 *lock
= CXD2880_TNRDMD_LOCK_RESULT_LOCKED
;
1165 else if (unlock_detected
)
1166 *lock
= CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED
;
1168 *lock
= CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT
;
1174 *lock
= CXD2880_TNRDMD_LOCK_RESULT_LOCKED
;
1176 } else if (!unlock_detected
) {
1177 *lock
= CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT
;
1182 cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub(tnr_dmd
, &sync_stat
,
1183 &unlock_detected_sub
);
1184 if (ret
!= CXD2880_RESULT_OK
)
1187 if (unlock_detected
&& unlock_detected_sub
)
1188 *lock
= CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED
;
1190 *lock
= CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT
;
1195 enum cxd2880_ret
cxd2880_tnrdmd_dvbt2_set_plp_cfg(struct cxd2880_tnrdmd
1196 *tnr_dmd
, u8 auto_plp
,
1199 enum cxd2880_ret ret
= CXD2880_RESULT_OK
;
1202 return CXD2880_RESULT_ERROR_ARG
;
1204 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_SUB
)
1205 return CXD2880_RESULT_ERROR_ARG
;
1207 if ((tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_SLEEP
) &&
1208 (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
))
1209 return CXD2880_RESULT_ERROR_SW_STATE
;
1211 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
1212 CXD2880_IO_TGT_DMD
, 0x00,
1213 0x23) != CXD2880_RESULT_OK
)
1214 return CXD2880_RESULT_ERROR_IO
;
1217 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
1218 CXD2880_IO_TGT_DMD
, 0xAF,
1219 plp_id
) != CXD2880_RESULT_OK
)
1220 return CXD2880_RESULT_ERROR_IO
;
1223 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
1224 CXD2880_IO_TGT_DMD
, 0xAD,
1225 auto_plp
? 0x00 : 0x01) != CXD2880_RESULT_OK
)
1226 return CXD2880_RESULT_ERROR_IO
;
1231 enum cxd2880_ret
cxd2880_tnrdmd_dvbt2_diver_fef_setting(struct cxd2880_tnrdmd
1234 enum cxd2880_ret ret
= CXD2880_RESULT_OK
;
1237 return CXD2880_RESULT_ERROR_ARG
;
1239 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_SUB
)
1240 return CXD2880_RESULT_ERROR_ARG
;
1242 if (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
)
1243 return CXD2880_RESULT_ERROR_SW_STATE
;
1245 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_SINGLE
)
1246 return CXD2880_RESULT_OK
;
1249 struct cxd2880_dvbt2_ofdm ofdm
;
1251 ret
= cxd2880_tnrdmd_dvbt2_mon_ofdm(tnr_dmd
, &ofdm
);
1252 if (ret
!= CXD2880_RESULT_OK
)
1256 return CXD2880_RESULT_OK
;
1260 u8 data
[] = { 0, 8, 0, 16,
1261 0, 32, 0, 64, 0, 128, 1, 0
1264 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
1265 CXD2880_IO_TGT_DMD
, 0x00,
1266 0x1D) != CXD2880_RESULT_OK
)
1267 return CXD2880_RESULT_ERROR_IO
;
1269 if (tnr_dmd
->io
->write_regs(tnr_dmd
->io
,
1270 CXD2880_IO_TGT_DMD
, 0x47, data
,
1271 12) != CXD2880_RESULT_OK
)
1272 return CXD2880_RESULT_ERROR_IO
;
1275 return CXD2880_RESULT_OK
;
1278 enum cxd2880_ret
cxd2880_tnrdmd_dvbt2_check_l1post_valid(struct cxd2880_tnrdmd
1282 enum cxd2880_ret ret
= CXD2880_RESULT_OK
;
1286 if ((!tnr_dmd
) || (!l1_post_valid
))
1287 return CXD2880_RESULT_ERROR_ARG
;
1289 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_SUB
)
1290 return CXD2880_RESULT_ERROR_ARG
;
1292 if ((tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_SLEEP
) &&
1293 (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
))
1294 return CXD2880_RESULT_ERROR_SW_STATE
;
1296 if (tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
1297 CXD2880_IO_TGT_DMD
, 0x00,
1298 0x0B) != CXD2880_RESULT_OK
)
1299 return CXD2880_RESULT_ERROR_IO
;
1301 if (tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
1302 CXD2880_IO_TGT_DMD
, 0x86, &data
,
1303 1) != CXD2880_RESULT_OK
)
1304 return CXD2880_RESULT_ERROR_IO
;
1306 *l1_post_valid
= data
& 0x01;