1 // SPDX-License-Identifier: GPL-2.0
3 * cxd2880_tnrdmd_dvbt2_mon.c
4 * Sony CXD2880 DVB-T2/T tuner + demodulator driver
5 * DVB-T2 monitor functions
7 * Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
10 #include "cxd2880_tnrdmd_mon.h"
11 #include "cxd2880_tnrdmd_dvbt2.h"
12 #include "cxd2880_tnrdmd_dvbt2_mon.h"
14 #include <media/dvb_math.h>
16 static const int ref_dbm_1000
[4][8] = {
17 {-96000, -95000, -94000, -93000, -92000, -92000, -98000, -97000},
18 {-91000, -89000, -88000, -87000, -86000, -86000, -93000, -92000},
19 {-86000, -85000, -83000, -82000, -81000, -80000, -89000, -88000},
20 {-82000, -80000, -78000, -76000, -75000, -74000, -86000, -84000},
23 int cxd2880_tnrdmd_dvbt2_mon_sync_stat(struct cxd2880_tnrdmd
24 *tnr_dmd
, u8
*sync_stat
,
31 if (!tnr_dmd
|| !sync_stat
|| !ts_lock_stat
|| !unlock_detected
)
34 if (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
)
37 if (tnr_dmd
->sys
!= CXD2880_DTV_SYS_DVBT2
)
40 ret
= tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
46 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
48 0x10, &data
, sizeof(data
));
52 *sync_stat
= data
& 0x07;
53 *ts_lock_stat
= ((data
& 0x20) ? 1 : 0);
54 *unlock_detected
= ((data
& 0x10) ? 1 : 0);
56 if (*sync_stat
== 0x07)
62 int cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub(struct cxd2880_tnrdmd
69 if (!tnr_dmd
|| !sync_stat
|| !unlock_detected
)
72 if (tnr_dmd
->diver_mode
!= CXD2880_TNRDMD_DIVERMODE_MAIN
)
75 return cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd
->diver_sub
,
81 int cxd2880_tnrdmd_dvbt2_mon_carrier_offset(struct cxd2880_tnrdmd
82 *tnr_dmd
, int *offset
)
88 u8 unlock_detected
= 0;
91 if (!tnr_dmd
|| !offset
)
94 if (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
)
97 if (tnr_dmd
->sys
!= CXD2880_DTV_SYS_DVBT2
)
100 ret
= slvt_freeze_reg(tnr_dmd
);
105 cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd
, &sync_state
,
109 slvt_unfreeze_reg(tnr_dmd
);
113 if (sync_state
!= 6) {
114 slvt_unfreeze_reg(tnr_dmd
);
118 ret
= tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
122 slvt_unfreeze_reg(tnr_dmd
);
126 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
128 0x30, data
, sizeof(data
));
130 slvt_unfreeze_reg(tnr_dmd
);
134 slvt_unfreeze_reg(tnr_dmd
);
137 ((data
[0] & 0x0f) << 24) | (data
[1] << 16) | (data
[2] << 8)
139 *offset
= cxd2880_convert2s_complement(ctl_val
, 28);
141 switch (tnr_dmd
->bandwidth
) {
142 case CXD2880_DTV_BW_1_7_MHZ
:
143 *offset
= -1 * ((*offset
) / 582);
145 case CXD2880_DTV_BW_5_MHZ
:
146 case CXD2880_DTV_BW_6_MHZ
:
147 case CXD2880_DTV_BW_7_MHZ
:
148 case CXD2880_DTV_BW_8_MHZ
:
149 *offset
= -1 * ((*offset
) * tnr_dmd
->bandwidth
/ 940);
158 int cxd2880_tnrdmd_dvbt2_mon_carrier_offset_sub(struct
163 if (!tnr_dmd
|| !offset
)
166 if (tnr_dmd
->diver_mode
!= CXD2880_TNRDMD_DIVERMODE_MAIN
)
169 return cxd2880_tnrdmd_dvbt2_mon_carrier_offset(tnr_dmd
->diver_sub
,
173 int cxd2880_tnrdmd_dvbt2_mon_l1_pre(struct cxd2880_tnrdmd
*tnr_dmd
,
174 struct cxd2880_dvbt2_l1pre
180 u8 unlock_detected
= 0;
182 enum cxd2880_dvbt2_profile profile
;
185 if (!tnr_dmd
|| !l1_pre
)
188 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_SUB
)
191 if (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
)
194 if (tnr_dmd
->sys
!= CXD2880_DTV_SYS_DVBT2
)
197 ret
= slvt_freeze_reg(tnr_dmd
);
202 cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd
, &sync_state
,
206 slvt_unfreeze_reg(tnr_dmd
);
210 if (sync_state
< 5) {
211 if (tnr_dmd
->diver_mode
==
212 CXD2880_TNRDMD_DIVERMODE_MAIN
) {
214 cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub
215 (tnr_dmd
, &sync_state
, &unlock_detected
);
217 slvt_unfreeze_reg(tnr_dmd
);
221 if (sync_state
< 5) {
222 slvt_unfreeze_reg(tnr_dmd
);
226 slvt_unfreeze_reg(tnr_dmd
);
231 ret
= cxd2880_tnrdmd_dvbt2_mon_profile(tnr_dmd
, &profile
);
233 slvt_unfreeze_reg(tnr_dmd
);
237 ret
= tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
241 slvt_unfreeze_reg(tnr_dmd
);
245 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
247 0x61, data
, sizeof(data
));
249 slvt_unfreeze_reg(tnr_dmd
);
252 slvt_unfreeze_reg(tnr_dmd
);
254 l1_pre
->type
= (enum cxd2880_dvbt2_l1pre_type
)data
[0];
255 l1_pre
->bw_ext
= data
[1] & 0x01;
256 l1_pre
->s1
= (enum cxd2880_dvbt2_s1
)(data
[2] & 0x07);
257 l1_pre
->s2
= data
[3] & 0x0f;
258 l1_pre
->l1_rep
= data
[4] & 0x01;
259 l1_pre
->gi
= (enum cxd2880_dvbt2_guard
)(data
[5] & 0x07);
260 l1_pre
->papr
= (enum cxd2880_dvbt2_papr
)(data
[6] & 0x0f);
262 (enum cxd2880_dvbt2_l1post_constell
)(data
[7] & 0x0f);
263 l1_pre
->cr
= (enum cxd2880_dvbt2_l1post_cr
)(data
[8] & 0x03);
265 (enum cxd2880_dvbt2_l1post_fec_type
)(data
[9] & 0x03);
266 l1_pre
->l1_post_size
= (data
[10] & 0x03) << 16;
267 l1_pre
->l1_post_size
|= (data
[11]) << 8;
268 l1_pre
->l1_post_size
|= (data
[12]);
269 l1_pre
->l1_post_info_size
= (data
[13] & 0x03) << 16;
270 l1_pre
->l1_post_info_size
|= (data
[14]) << 8;
271 l1_pre
->l1_post_info_size
|= (data
[15]);
272 l1_pre
->pp
= (enum cxd2880_dvbt2_pp
)(data
[16] & 0x0f);
273 l1_pre
->tx_id_availability
= data
[17];
274 l1_pre
->cell_id
= (data
[18] << 8);
275 l1_pre
->cell_id
|= (data
[19]);
276 l1_pre
->network_id
= (data
[20] << 8);
277 l1_pre
->network_id
|= (data
[21]);
278 l1_pre
->sys_id
= (data
[22] << 8);
279 l1_pre
->sys_id
|= (data
[23]);
280 l1_pre
->num_frames
= data
[24];
281 l1_pre
->num_symbols
= (data
[25] & 0x0f) << 8;
282 l1_pre
->num_symbols
|= data
[26];
283 l1_pre
->regen
= data
[27] & 0x07;
284 l1_pre
->post_ext
= data
[28] & 0x01;
285 l1_pre
->num_rf_freqs
= data
[29] & 0x07;
286 l1_pre
->rf_idx
= data
[30] & 0x07;
287 version
= (data
[31] & 0x03) << 2;
288 version
|= (data
[32] & 0xc0) >> 6;
289 l1_pre
->t2_version
= (enum cxd2880_dvbt2_version
)version
;
290 l1_pre
->l1_post_scrambled
= (data
[32] & 0x20) >> 5;
291 l1_pre
->t2_base_lite
= (data
[32] & 0x10) >> 4;
292 l1_pre
->crc32
= (data
[33] << 24);
293 l1_pre
->crc32
|= (data
[34] << 16);
294 l1_pre
->crc32
|= (data
[35] << 8);
295 l1_pre
->crc32
|= data
[36];
297 if (profile
== CXD2880_DVBT2_PROFILE_BASE
) {
298 switch ((l1_pre
->s2
>> 1)) {
299 case CXD2880_DVBT2_BASE_S2_M1K_G_ANY
:
300 l1_pre
->fft_mode
= CXD2880_DVBT2_M1K
;
302 case CXD2880_DVBT2_BASE_S2_M2K_G_ANY
:
303 l1_pre
->fft_mode
= CXD2880_DVBT2_M2K
;
305 case CXD2880_DVBT2_BASE_S2_M4K_G_ANY
:
306 l1_pre
->fft_mode
= CXD2880_DVBT2_M4K
;
308 case CXD2880_DVBT2_BASE_S2_M8K_G_DVBT
:
309 case CXD2880_DVBT2_BASE_S2_M8K_G_DVBT2
:
310 l1_pre
->fft_mode
= CXD2880_DVBT2_M8K
;
312 case CXD2880_DVBT2_BASE_S2_M16K_G_ANY
:
313 l1_pre
->fft_mode
= CXD2880_DVBT2_M16K
;
315 case CXD2880_DVBT2_BASE_S2_M32K_G_DVBT
:
316 case CXD2880_DVBT2_BASE_S2_M32K_G_DVBT2
:
317 l1_pre
->fft_mode
= CXD2880_DVBT2_M32K
;
322 } else if (profile
== CXD2880_DVBT2_PROFILE_LITE
) {
323 switch ((l1_pre
->s2
>> 1)) {
324 case CXD2880_DVBT2_LITE_S2_M2K_G_ANY
:
325 l1_pre
->fft_mode
= CXD2880_DVBT2_M2K
;
327 case CXD2880_DVBT2_LITE_S2_M4K_G_ANY
:
328 l1_pre
->fft_mode
= CXD2880_DVBT2_M4K
;
330 case CXD2880_DVBT2_LITE_S2_M8K_G_DVBT
:
331 case CXD2880_DVBT2_LITE_S2_M8K_G_DVBT2
:
332 l1_pre
->fft_mode
= CXD2880_DVBT2_M8K
;
334 case CXD2880_DVBT2_LITE_S2_M16K_G_DVBT
:
335 case CXD2880_DVBT2_LITE_S2_M16K_G_DVBT2
:
336 l1_pre
->fft_mode
= CXD2880_DVBT2_M16K
;
345 l1_pre
->mixed
= l1_pre
->s2
& 0x01;
350 int cxd2880_tnrdmd_dvbt2_mon_version(struct cxd2880_tnrdmd
352 enum cxd2880_dvbt2_version
358 u8 unlock_detected
= 0;
362 if (!tnr_dmd
|| !ver
)
365 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_SUB
)
368 if (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
)
371 if (tnr_dmd
->sys
!= CXD2880_DTV_SYS_DVBT2
)
374 ret
= slvt_freeze_reg(tnr_dmd
);
379 cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd
, &sync_state
,
383 slvt_unfreeze_reg(tnr_dmd
);
387 if (sync_state
< 5) {
388 if (tnr_dmd
->diver_mode
==
389 CXD2880_TNRDMD_DIVERMODE_MAIN
) {
391 cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub
392 (tnr_dmd
, &sync_state
, &unlock_detected
);
394 slvt_unfreeze_reg(tnr_dmd
);
398 if (sync_state
< 5) {
399 slvt_unfreeze_reg(tnr_dmd
);
403 slvt_unfreeze_reg(tnr_dmd
);
408 ret
= tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
412 slvt_unfreeze_reg(tnr_dmd
);
416 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
418 0x80, data
, sizeof(data
));
420 slvt_unfreeze_reg(tnr_dmd
);
424 slvt_unfreeze_reg(tnr_dmd
);
426 version
= ((data
[0] & 0x03) << 2);
427 version
|= ((data
[1] & 0xc0) >> 6);
428 *ver
= (enum cxd2880_dvbt2_version
)version
;
433 int cxd2880_tnrdmd_dvbt2_mon_ofdm(struct cxd2880_tnrdmd
*tnr_dmd
,
434 struct cxd2880_dvbt2_ofdm
*ofdm
)
439 u8 unlock_detected
= 0;
442 if (!tnr_dmd
|| !ofdm
)
445 if (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
)
448 if (tnr_dmd
->sys
!= CXD2880_DTV_SYS_DVBT2
)
451 ret
= slvt_freeze_reg(tnr_dmd
);
456 cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd
, &sync_state
,
460 slvt_unfreeze_reg(tnr_dmd
);
464 if (sync_state
!= 6) {
465 slvt_unfreeze_reg(tnr_dmd
);
469 if (tnr_dmd
->diver_mode
==
470 CXD2880_TNRDMD_DIVERMODE_MAIN
)
472 cxd2880_tnrdmd_dvbt2_mon_ofdm(tnr_dmd
->diver_sub
,
478 ret
= tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
482 slvt_unfreeze_reg(tnr_dmd
);
486 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
488 0x1d, data
, sizeof(data
));
490 slvt_unfreeze_reg(tnr_dmd
);
494 slvt_unfreeze_reg(tnr_dmd
);
496 ofdm
->mixed
= ((data
[0] & 0x20) ? 1 : 0);
497 ofdm
->is_miso
= ((data
[0] & 0x10) >> 4);
498 ofdm
->mode
= (enum cxd2880_dvbt2_mode
)(data
[0] & 0x07);
499 ofdm
->gi
= (enum cxd2880_dvbt2_guard
)((data
[1] & 0x70) >> 4);
500 ofdm
->pp
= (enum cxd2880_dvbt2_pp
)(data
[1] & 0x07);
501 ofdm
->bw_ext
= (data
[2] & 0x10) >> 4;
502 ofdm
->papr
= (enum cxd2880_dvbt2_papr
)(data
[2] & 0x0f);
503 ofdm
->num_symbols
= (data
[3] << 8) | data
[4];
508 int cxd2880_tnrdmd_dvbt2_mon_data_plps(struct cxd2880_tnrdmd
509 *tnr_dmd
, u8
*plp_ids
,
515 if (!tnr_dmd
|| !num_plps
)
518 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_SUB
)
521 if (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
)
524 if (tnr_dmd
->sys
!= CXD2880_DTV_SYS_DVBT2
)
527 ret
= tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
533 ret
= slvt_freeze_reg(tnr_dmd
);
537 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
539 0x86, &l1_post_ok
, 1);
541 slvt_unfreeze_reg(tnr_dmd
);
545 if (!(l1_post_ok
& 0x01)) {
546 slvt_unfreeze_reg(tnr_dmd
);
550 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
554 slvt_unfreeze_reg(tnr_dmd
);
558 if (*num_plps
== 0) {
559 slvt_unfreeze_reg(tnr_dmd
);
564 slvt_unfreeze_reg(tnr_dmd
);
568 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
575 slvt_unfreeze_reg(tnr_dmd
);
579 if (*num_plps
> 62) {
580 ret
= tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
584 slvt_unfreeze_reg(tnr_dmd
);
588 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
593 slvt_unfreeze_reg(tnr_dmd
);
598 slvt_unfreeze_reg(tnr_dmd
);
603 int cxd2880_tnrdmd_dvbt2_mon_active_plp(struct cxd2880_tnrdmd
606 cxd2880_dvbt2_plp_btype
608 struct cxd2880_dvbt2_plp
617 if (!tnr_dmd
|| !plp_info
)
620 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_SUB
)
623 if (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
)
626 if (tnr_dmd
->sys
!= CXD2880_DTV_SYS_DVBT2
)
629 ret
= slvt_freeze_reg(tnr_dmd
);
633 ret
= tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
637 slvt_unfreeze_reg(tnr_dmd
);
641 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
643 0x86, &l1_post_ok
, 1);
645 slvt_unfreeze_reg(tnr_dmd
);
650 slvt_unfreeze_reg(tnr_dmd
);
654 if (type
== CXD2880_DVBT2_PLP_COMMON
)
659 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
661 addr
, data
, sizeof(data
));
663 slvt_unfreeze_reg(tnr_dmd
);
667 slvt_unfreeze_reg(tnr_dmd
);
669 if (type
== CXD2880_DVBT2_PLP_COMMON
&& !data
[13])
672 plp_info
->id
= data
[index
++];
674 (enum cxd2880_dvbt2_plp_type
)(data
[index
++] & 0x07);
676 (enum cxd2880_dvbt2_plp_payload
)(data
[index
++] & 0x1f);
677 plp_info
->ff
= data
[index
++] & 0x01;
678 plp_info
->first_rf_idx
= data
[index
++] & 0x07;
679 plp_info
->first_frm_idx
= data
[index
++];
680 plp_info
->group_id
= data
[index
++];
682 (enum cxd2880_dvbt2_plp_code_rate
)(data
[index
++] & 0x07);
684 (enum cxd2880_dvbt2_plp_constell
)(data
[index
++] & 0x07);
685 plp_info
->rot
= data
[index
++] & 0x01;
687 (enum cxd2880_dvbt2_plp_fec
)(data
[index
++] & 0x03);
688 plp_info
->num_blocks_max
= (data
[index
++] & 0x03) << 8;
689 plp_info
->num_blocks_max
|= data
[index
++];
690 plp_info
->frm_int
= data
[index
++];
691 plp_info
->til_len
= data
[index
++];
692 plp_info
->til_type
= data
[index
++] & 0x01;
694 plp_info
->in_band_a_flag
= data
[index
++] & 0x01;
695 plp_info
->rsvd
= data
[index
++] << 8;
696 plp_info
->rsvd
|= data
[index
++];
698 plp_info
->in_band_b_flag
=
699 (plp_info
->rsvd
& 0x8000) >> 15;
701 (enum cxd2880_dvbt2_plp_mode
)((plp_info
->rsvd
& 0x000c) >> 2);
702 plp_info
->static_flag
= (plp_info
->rsvd
& 0x0002) >> 1;
703 plp_info
->static_padding_flag
= plp_info
->rsvd
& 0x0001;
704 plp_info
->rsvd
= (plp_info
->rsvd
& 0x7ff0) >> 4;
709 int cxd2880_tnrdmd_dvbt2_mon_data_plp_error(struct cxd2880_tnrdmd
716 if (!tnr_dmd
|| !plp_error
)
719 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_SUB
)
722 if (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
)
725 if (tnr_dmd
->sys
!= CXD2880_DTV_SYS_DVBT2
)
728 ret
= slvt_freeze_reg(tnr_dmd
);
732 ret
= tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
736 slvt_unfreeze_reg(tnr_dmd
);
740 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
744 slvt_unfreeze_reg(tnr_dmd
);
748 if ((data
& 0x01) == 0x00) {
749 slvt_unfreeze_reg(tnr_dmd
);
753 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
757 slvt_unfreeze_reg(tnr_dmd
);
761 slvt_unfreeze_reg(tnr_dmd
);
763 *plp_error
= data
& 0x01;
768 int cxd2880_tnrdmd_dvbt2_mon_l1_change(struct cxd2880_tnrdmd
769 *tnr_dmd
, u8
*l1_change
)
774 u8 unlock_detected
= 0;
777 if (!tnr_dmd
|| !l1_change
)
780 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_SUB
)
783 if (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
)
786 if (tnr_dmd
->sys
!= CXD2880_DTV_SYS_DVBT2
)
789 ret
= slvt_freeze_reg(tnr_dmd
);
794 cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd
, &sync_state
,
798 slvt_unfreeze_reg(tnr_dmd
);
802 if (sync_state
< 5) {
803 if (tnr_dmd
->diver_mode
==
804 CXD2880_TNRDMD_DIVERMODE_MAIN
) {
806 cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub
807 (tnr_dmd
, &sync_state
, &unlock_detected
);
809 slvt_unfreeze_reg(tnr_dmd
);
813 if (sync_state
< 5) {
814 slvt_unfreeze_reg(tnr_dmd
);
818 slvt_unfreeze_reg(tnr_dmd
);
823 ret
= tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
827 slvt_unfreeze_reg(tnr_dmd
);
831 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
833 0x5f, &data
, sizeof(data
));
835 slvt_unfreeze_reg(tnr_dmd
);
839 *l1_change
= data
& 0x01;
841 ret
= tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
845 slvt_unfreeze_reg(tnr_dmd
);
849 ret
= tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
853 slvt_unfreeze_reg(tnr_dmd
);
857 slvt_unfreeze_reg(tnr_dmd
);
862 int cxd2880_tnrdmd_dvbt2_mon_l1_post(struct cxd2880_tnrdmd
864 struct cxd2880_dvbt2_l1post
870 if (!tnr_dmd
|| !l1_post
)
873 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_SUB
)
876 if (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
)
879 if (tnr_dmd
->sys
!= CXD2880_DTV_SYS_DVBT2
)
882 ret
= tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
888 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
890 0x86, data
, sizeof(data
));
894 if (!(data
[0] & 0x01))
897 l1_post
->sub_slices_per_frame
= (data
[1] & 0x7f) << 8;
898 l1_post
->sub_slices_per_frame
|= data
[2];
899 l1_post
->num_plps
= data
[3];
900 l1_post
->num_aux
= data
[4] & 0x0f;
901 l1_post
->aux_cfg_rfu
= data
[5];
902 l1_post
->rf_idx
= data
[6] & 0x07;
903 l1_post
->freq
= data
[7] << 24;
904 l1_post
->freq
|= data
[8] << 16;
905 l1_post
->freq
|= data
[9] << 8;
906 l1_post
->freq
|= data
[10];
907 l1_post
->fef_type
= data
[11] & 0x0f;
908 l1_post
->fef_length
= data
[12] << 16;
909 l1_post
->fef_length
|= data
[13] << 8;
910 l1_post
->fef_length
|= data
[14];
911 l1_post
->fef_intvl
= data
[15];
916 int cxd2880_tnrdmd_dvbt2_mon_bbheader(struct cxd2880_tnrdmd
918 enum cxd2880_dvbt2_plp_btype
920 struct cxd2880_dvbt2_bbheader
925 u8 unlock_detected
= 0;
930 if (!tnr_dmd
|| !bbheader
)
933 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_SUB
)
936 if (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
)
939 if (tnr_dmd
->sys
!= CXD2880_DTV_SYS_DVBT2
)
942 ret
= slvt_freeze_reg(tnr_dmd
);
947 cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd
, &sync_state
,
951 slvt_unfreeze_reg(tnr_dmd
);
956 slvt_unfreeze_reg(tnr_dmd
);
960 ret
= tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
964 slvt_unfreeze_reg(tnr_dmd
);
968 if (type
== CXD2880_DVBT2_PLP_COMMON
) {
972 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
974 0x86, &l1_post_ok
, 1);
976 slvt_unfreeze_reg(tnr_dmd
);
980 if (!(l1_post_ok
& 0x01)) {
981 slvt_unfreeze_reg(tnr_dmd
);
985 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
989 slvt_unfreeze_reg(tnr_dmd
);
994 slvt_unfreeze_reg(tnr_dmd
);
999 if (type
== CXD2880_DVBT2_PLP_COMMON
)
1004 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
1006 addr
, data
, sizeof(data
));
1008 slvt_unfreeze_reg(tnr_dmd
);
1012 slvt_unfreeze_reg(tnr_dmd
);
1014 bbheader
->stream_input
=
1015 (enum cxd2880_dvbt2_stream
)((data
[0] >> 6) & 0x03);
1016 bbheader
->is_single_input_stream
= (data
[0] >> 5) & 0x01;
1017 bbheader
->is_constant_coding_modulation
=
1018 (data
[0] >> 4) & 0x01;
1019 bbheader
->issy_indicator
= (data
[0] >> 3) & 0x01;
1020 bbheader
->null_packet_deletion
= (data
[0] >> 2) & 0x01;
1021 bbheader
->ext
= data
[0] & 0x03;
1023 bbheader
->input_stream_identifier
= data
[1];
1024 bbheader
->plp_mode
=
1025 (data
[3] & 0x01) ? CXD2880_DVBT2_PLP_MODE_HEM
:
1026 CXD2880_DVBT2_PLP_MODE_NM
;
1027 bbheader
->data_field_length
= (data
[4] << 8) | data
[5];
1029 if (bbheader
->plp_mode
== CXD2880_DVBT2_PLP_MODE_NM
) {
1030 bbheader
->user_packet_length
=
1031 (data
[6] << 8) | data
[7];
1032 bbheader
->sync_byte
= data
[8];
1035 bbheader
->user_packet_length
= 0;
1036 bbheader
->sync_byte
= 0;
1038 (data
[11] << 16) | (data
[12] << 8) | data
[13];
1044 int cxd2880_tnrdmd_dvbt2_mon_in_bandb_ts_rate(struct cxd2880_tnrdmd
1047 cxd2880_dvbt2_plp_btype
1053 u8 unlock_detected
= 0;
1060 if (!tnr_dmd
|| !ts_rate_bps
)
1063 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_SUB
)
1066 if (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
)
1069 if (tnr_dmd
->sys
!= CXD2880_DTV_SYS_DVBT2
)
1072 ret
= slvt_freeze_reg(tnr_dmd
);
1077 cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd
, &sync_state
,
1081 slvt_unfreeze_reg(tnr_dmd
);
1086 slvt_unfreeze_reg(tnr_dmd
);
1090 ret
= tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
1094 slvt_unfreeze_reg(tnr_dmd
);
1098 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
1100 0x86, &l1_post_ok
, 1);
1102 slvt_unfreeze_reg(tnr_dmd
);
1106 if (!(l1_post_ok
& 0x01)) {
1107 slvt_unfreeze_reg(tnr_dmd
);
1111 if (type
== CXD2880_DVBT2_PLP_COMMON
)
1116 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
1120 slvt_unfreeze_reg(tnr_dmd
);
1124 if ((data
[0] & 0x80) == 0x00) {
1125 slvt_unfreeze_reg(tnr_dmd
);
1129 ret
= tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
1133 slvt_unfreeze_reg(tnr_dmd
);
1137 if (type
== CXD2880_DVBT2_PLP_COMMON
)
1142 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
1146 slvt_unfreeze_reg(tnr_dmd
);
1150 *ts_rate_bps
= ((data
[0] & 0x07) << 24) | (data
[1] << 16) |
1151 (data
[2] << 8) | data
[3];
1156 int cxd2880_tnrdmd_dvbt2_mon_spectrum_sense(struct cxd2880_tnrdmd
1159 cxd2880_tnrdmd_spectrum_sense
1164 u8 early_unlock
= 0;
1168 if (!tnr_dmd
|| !sense
)
1171 if (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
)
1174 if (tnr_dmd
->sys
!= CXD2880_DTV_SYS_DVBT2
)
1177 ret
= slvt_freeze_reg(tnr_dmd
);
1182 cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd
, &sync_state
, &ts_lock
,
1185 slvt_unfreeze_reg(tnr_dmd
);
1189 if (sync_state
!= 6) {
1190 slvt_unfreeze_reg(tnr_dmd
);
1194 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_MAIN
)
1196 cxd2880_tnrdmd_dvbt2_mon_spectrum_sense(tnr_dmd
->diver_sub
,
1202 ret
= tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
1206 slvt_unfreeze_reg(tnr_dmd
);
1210 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
1212 0x2f, &data
, sizeof(data
));
1214 slvt_unfreeze_reg(tnr_dmd
);
1218 slvt_unfreeze_reg(tnr_dmd
);
1221 (data
& 0x01) ? CXD2880_TNRDMD_SPECTRUM_INV
:
1222 CXD2880_TNRDMD_SPECTRUM_NORMAL
;
1227 static int dvbt2_read_snr_reg(struct cxd2880_tnrdmd
*tnr_dmd
,
1232 u8 unlock_detected
= 0;
1236 if (!tnr_dmd
|| !reg_value
)
1239 ret
= slvt_freeze_reg(tnr_dmd
);
1244 cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd
, &sync_state
,
1248 slvt_unfreeze_reg(tnr_dmd
);
1252 if (sync_state
!= 6) {
1253 slvt_unfreeze_reg(tnr_dmd
);
1257 ret
= tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
1261 slvt_unfreeze_reg(tnr_dmd
);
1265 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
1267 0x13, data
, sizeof(data
));
1269 slvt_unfreeze_reg(tnr_dmd
);
1273 slvt_unfreeze_reg(tnr_dmd
);
1275 *reg_value
= (data
[0] << 8) | data
[1];
1280 static int dvbt2_calc_snr(struct cxd2880_tnrdmd
*tnr_dmd
,
1281 u32 reg_value
, int *snr
)
1283 if (!tnr_dmd
|| !snr
)
1289 if (reg_value
> 10876)
1292 *snr
= intlog10(reg_value
) - intlog10(12600 - reg_value
);
1293 *snr
= (*snr
+ 839) / 1678 + 32000;
1298 int cxd2880_tnrdmd_dvbt2_mon_snr(struct cxd2880_tnrdmd
*tnr_dmd
,
1304 if (!tnr_dmd
|| !snr
)
1307 *snr
= -1000 * 1000;
1309 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_SUB
)
1312 if (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
)
1315 if (tnr_dmd
->sys
!= CXD2880_DTV_SYS_DVBT2
)
1318 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_SINGLE
) {
1319 ret
= dvbt2_read_snr_reg(tnr_dmd
, ®_value
);
1323 ret
= dvbt2_calc_snr(tnr_dmd
, reg_value
, snr
);
1329 cxd2880_tnrdmd_dvbt2_mon_snr_diver(tnr_dmd
, snr
, &snr_main
,
1336 int cxd2880_tnrdmd_dvbt2_mon_snr_diver(struct cxd2880_tnrdmd
1338 int *snr_main
, int *snr_sub
)
1341 u32 reg_value_sum
= 0;
1344 if (!tnr_dmd
|| !snr
|| !snr_main
|| !snr_sub
)
1347 *snr
= -1000 * 1000;
1348 *snr_main
= -1000 * 1000;
1349 *snr_sub
= -1000 * 1000;
1351 if (tnr_dmd
->diver_mode
!= CXD2880_TNRDMD_DIVERMODE_MAIN
)
1354 if (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
)
1357 if (tnr_dmd
->sys
!= CXD2880_DTV_SYS_DVBT2
)
1360 ret
= dvbt2_read_snr_reg(tnr_dmd
, ®_value
);
1362 ret
= dvbt2_calc_snr(tnr_dmd
, reg_value
, snr_main
);
1365 } else if (ret
== -EAGAIN
) {
1371 reg_value_sum
+= reg_value
;
1373 ret
= dvbt2_read_snr_reg(tnr_dmd
->diver_sub
, ®_value
);
1375 ret
= dvbt2_calc_snr(tnr_dmd
->diver_sub
, reg_value
, snr_sub
);
1378 } else if (ret
== -EAGAIN
) {
1384 reg_value_sum
+= reg_value
;
1386 return dvbt2_calc_snr(tnr_dmd
, reg_value_sum
, snr
);
1389 int cxd2880_tnrdmd_dvbt2_mon_packet_error_number(struct
1397 if (!tnr_dmd
|| !pen
)
1400 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_SUB
)
1403 if (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
)
1406 if (tnr_dmd
->sys
!= CXD2880_DTV_SYS_DVBT2
)
1409 ret
= tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
1415 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
1417 0x39, data
, sizeof(data
));
1421 if (!(data
[0] & 0x01))
1424 *pen
= ((data
[1] << 8) | data
[2]);
1429 int cxd2880_tnrdmd_dvbt2_mon_sampling_offset(struct cxd2880_tnrdmd
1433 u8 nominal_rate_reg
[5];
1434 u32 trl_ctl_val
= 0;
1435 u32 trcg_nominal_rate
= 0;
1441 u8 unlock_detected
= 0;
1444 if (!tnr_dmd
|| !ppm
)
1447 if (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
)
1450 if (tnr_dmd
->sys
!= CXD2880_DTV_SYS_DVBT2
)
1453 ret
= slvt_freeze_reg(tnr_dmd
);
1458 cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd
, &sync_state
,
1462 slvt_unfreeze_reg(tnr_dmd
);
1466 if (sync_state
!= 6) {
1467 slvt_unfreeze_reg(tnr_dmd
);
1471 ret
= tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
1475 slvt_unfreeze_reg(tnr_dmd
);
1479 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
1482 sizeof(ctl_val_reg
));
1484 slvt_unfreeze_reg(tnr_dmd
);
1488 ret
= tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
1492 slvt_unfreeze_reg(tnr_dmd
);
1496 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
1498 0x10, nominal_rate_reg
,
1499 sizeof(nominal_rate_reg
));
1501 slvt_unfreeze_reg(tnr_dmd
);
1505 slvt_unfreeze_reg(tnr_dmd
);
1508 (ctl_val_reg
[0] & 0x7f) - (nominal_rate_reg
[0] & 0x7f);
1510 if (diff_upper
< -1 || diff_upper
> 1)
1513 trl_ctl_val
= ctl_val_reg
[1] << 24;
1514 trl_ctl_val
|= ctl_val_reg
[2] << 16;
1515 trl_ctl_val
|= ctl_val_reg
[3] << 8;
1516 trl_ctl_val
|= ctl_val_reg
[4];
1518 trcg_nominal_rate
= nominal_rate_reg
[1] << 24;
1519 trcg_nominal_rate
|= nominal_rate_reg
[2] << 16;
1520 trcg_nominal_rate
|= nominal_rate_reg
[3] << 8;
1521 trcg_nominal_rate
|= nominal_rate_reg
[4];
1524 trcg_nominal_rate
>>= 1;
1526 if (diff_upper
== 1)
1528 (int)((trl_ctl_val
+ 0x80000000u
) -
1530 else if (diff_upper
== -1)
1532 -(int)((trcg_nominal_rate
+ 0x80000000u
) -
1535 num
= (int)(trl_ctl_val
- trcg_nominal_rate
);
1537 den
= (nominal_rate_reg
[0] & 0x7f) << 24;
1538 den
|= nominal_rate_reg
[1] << 16;
1539 den
|= nominal_rate_reg
[2] << 8;
1540 den
|= nominal_rate_reg
[3];
1541 den
= (den
+ (390625 / 2)) / 390625;
1546 *ppm
= (num
+ (den
/ 2)) / den
;
1548 *ppm
= (num
- (den
/ 2)) / den
;
1553 int cxd2880_tnrdmd_dvbt2_mon_sampling_offset_sub(struct
1558 if (!tnr_dmd
|| !ppm
)
1561 if (tnr_dmd
->diver_mode
!= CXD2880_TNRDMD_DIVERMODE_MAIN
)
1564 return cxd2880_tnrdmd_dvbt2_mon_sampling_offset(tnr_dmd
->diver_sub
,
1568 int cxd2880_tnrdmd_dvbt2_mon_qam(struct cxd2880_tnrdmd
*tnr_dmd
,
1569 enum cxd2880_dvbt2_plp_btype type
,
1570 enum cxd2880_dvbt2_plp_constell
*qam
)
1576 if (!tnr_dmd
|| !qam
)
1579 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_SUB
)
1582 if (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
)
1585 if (tnr_dmd
->sys
!= CXD2880_DTV_SYS_DVBT2
)
1588 ret
= slvt_freeze_reg(tnr_dmd
);
1592 ret
= tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
1596 slvt_unfreeze_reg(tnr_dmd
);
1600 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
1602 0x86, &l1_post_ok
, 1);
1604 slvt_unfreeze_reg(tnr_dmd
);
1608 if (!(l1_post_ok
& 0x01)) {
1609 slvt_unfreeze_reg(tnr_dmd
);
1613 if (type
== CXD2880_DVBT2_PLP_COMMON
) {
1614 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
1618 slvt_unfreeze_reg(tnr_dmd
);
1623 slvt_unfreeze_reg(tnr_dmd
);
1627 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
1631 slvt_unfreeze_reg(tnr_dmd
);
1635 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
1639 slvt_unfreeze_reg(tnr_dmd
);
1644 slvt_unfreeze_reg(tnr_dmd
);
1646 *qam
= (enum cxd2880_dvbt2_plp_constell
)(data
& 0x07);
1651 int cxd2880_tnrdmd_dvbt2_mon_code_rate(struct cxd2880_tnrdmd
1653 enum cxd2880_dvbt2_plp_btype
1656 cxd2880_dvbt2_plp_code_rate
1663 if (!tnr_dmd
|| !code_rate
)
1666 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_SUB
)
1669 if (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
)
1672 if (tnr_dmd
->sys
!= CXD2880_DTV_SYS_DVBT2
)
1675 ret
= slvt_freeze_reg(tnr_dmd
);
1679 ret
= tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
1683 slvt_unfreeze_reg(tnr_dmd
);
1687 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
1689 0x86, &l1_post_ok
, 1);
1691 slvt_unfreeze_reg(tnr_dmd
);
1695 if (!(l1_post_ok
& 0x01)) {
1696 slvt_unfreeze_reg(tnr_dmd
);
1700 if (type
== CXD2880_DVBT2_PLP_COMMON
) {
1701 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
1705 slvt_unfreeze_reg(tnr_dmd
);
1710 slvt_unfreeze_reg(tnr_dmd
);
1714 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
1718 slvt_unfreeze_reg(tnr_dmd
);
1722 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
1726 slvt_unfreeze_reg(tnr_dmd
);
1731 slvt_unfreeze_reg(tnr_dmd
);
1733 *code_rate
= (enum cxd2880_dvbt2_plp_code_rate
)(data
& 0x07);
1738 int cxd2880_tnrdmd_dvbt2_mon_profile(struct cxd2880_tnrdmd
1740 enum cxd2880_dvbt2_profile
1746 if (!tnr_dmd
|| !profile
)
1749 if (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
)
1752 if (tnr_dmd
->sys
!= CXD2880_DTV_SYS_DVBT2
)
1755 ret
= tnr_dmd
->io
->write_reg(tnr_dmd
->io
,
1761 ret
= tnr_dmd
->io
->read_regs(tnr_dmd
->io
,
1763 0x22, &data
, sizeof(data
));
1769 *profile
= CXD2880_DVBT2_PROFILE_LITE
;
1771 *profile
= CXD2880_DVBT2_PROFILE_BASE
;
1774 if (tnr_dmd
->diver_mode
==
1775 CXD2880_TNRDMD_DIVERMODE_MAIN
)
1777 cxd2880_tnrdmd_dvbt2_mon_profile(tnr_dmd
->diver_sub
,
1786 static int dvbt2_calc_ssi(struct cxd2880_tnrdmd
*tnr_dmd
,
1787 int rf_lvl
, u8
*ssi
)
1789 enum cxd2880_dvbt2_plp_constell qam
;
1790 enum cxd2880_dvbt2_plp_code_rate code_rate
;
1795 if (!tnr_dmd
|| !ssi
)
1799 cxd2880_tnrdmd_dvbt2_mon_qam(tnr_dmd
, CXD2880_DVBT2_PLP_DATA
, &qam
);
1804 cxd2880_tnrdmd_dvbt2_mon_code_rate(tnr_dmd
, CXD2880_DVBT2_PLP_DATA
,
1809 if (code_rate
> CXD2880_DVBT2_R2_5
|| qam
> CXD2880_DVBT2_QAM256
)
1812 prel
= rf_lvl
- ref_dbm_1000
[qam
][code_rate
];
1817 temp_ssi
= ((2 * (prel
+ 15000)) + 1500) / 3000;
1818 else if (prel
< 20000)
1819 temp_ssi
= (((4 * prel
) + 500) / 1000) + 10;
1820 else if (prel
< 35000)
1821 temp_ssi
= (((2 * (prel
- 20000)) + 1500) / 3000) + 90;
1825 *ssi
= (temp_ssi
> 100) ? 100 : (u8
)temp_ssi
;
1830 int cxd2880_tnrdmd_dvbt2_mon_ssi(struct cxd2880_tnrdmd
*tnr_dmd
,
1836 if (!tnr_dmd
|| !ssi
)
1839 if (tnr_dmd
->diver_mode
== CXD2880_TNRDMD_DIVERMODE_SUB
)
1842 if (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
)
1845 if (tnr_dmd
->sys
!= CXD2880_DTV_SYS_DVBT2
)
1848 ret
= cxd2880_tnrdmd_mon_rf_lvl(tnr_dmd
, &rf_lvl
);
1852 return dvbt2_calc_ssi(tnr_dmd
, rf_lvl
, ssi
);
1855 int cxd2880_tnrdmd_dvbt2_mon_ssi_sub(struct cxd2880_tnrdmd
1861 if (!tnr_dmd
|| !ssi
)
1864 if (tnr_dmd
->diver_mode
!= CXD2880_TNRDMD_DIVERMODE_MAIN
)
1867 if (tnr_dmd
->state
!= CXD2880_TNRDMD_STATE_ACTIVE
)
1870 if (tnr_dmd
->sys
!= CXD2880_DTV_SYS_DVBT2
)
1873 ret
= cxd2880_tnrdmd_mon_rf_lvl(tnr_dmd
->diver_sub
, &rf_lvl
);
1877 return dvbt2_calc_ssi(tnr_dmd
, rf_lvl
, ssi
);