root/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt2_mon.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cxd2880_tnrdmd_dvbt2_mon_sync_stat
  2. cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub
  3. cxd2880_tnrdmd_dvbt2_mon_carrier_offset
  4. cxd2880_tnrdmd_dvbt2_mon_carrier_offset_sub
  5. cxd2880_tnrdmd_dvbt2_mon_l1_pre
  6. cxd2880_tnrdmd_dvbt2_mon_version
  7. cxd2880_tnrdmd_dvbt2_mon_ofdm
  8. cxd2880_tnrdmd_dvbt2_mon_data_plps
  9. cxd2880_tnrdmd_dvbt2_mon_active_plp
  10. cxd2880_tnrdmd_dvbt2_mon_data_plp_error
  11. cxd2880_tnrdmd_dvbt2_mon_l1_change
  12. cxd2880_tnrdmd_dvbt2_mon_l1_post
  13. cxd2880_tnrdmd_dvbt2_mon_bbheader
  14. cxd2880_tnrdmd_dvbt2_mon_in_bandb_ts_rate
  15. cxd2880_tnrdmd_dvbt2_mon_spectrum_sense
  16. dvbt2_read_snr_reg
  17. dvbt2_calc_snr
  18. cxd2880_tnrdmd_dvbt2_mon_snr
  19. cxd2880_tnrdmd_dvbt2_mon_snr_diver
  20. cxd2880_tnrdmd_dvbt2_mon_packet_error_number
  21. cxd2880_tnrdmd_dvbt2_mon_sampling_offset
  22. cxd2880_tnrdmd_dvbt2_mon_sampling_offset_sub
  23. cxd2880_tnrdmd_dvbt2_mon_qam
  24. cxd2880_tnrdmd_dvbt2_mon_code_rate
  25. cxd2880_tnrdmd_dvbt2_mon_profile
  26. dvbt2_calc_ssi
  27. cxd2880_tnrdmd_dvbt2_mon_ssi
  28. cxd2880_tnrdmd_dvbt2_mon_ssi_sub

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * cxd2880_tnrdmd_dvbt2_mon.c
   4  * Sony CXD2880 DVB-T2/T tuner + demodulator driver
   5  * DVB-T2 monitor functions
   6  *
   7  * Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
   8  */
   9 
  10 #include "cxd2880_tnrdmd_mon.h"
  11 #include "cxd2880_tnrdmd_dvbt2.h"
  12 #include "cxd2880_tnrdmd_dvbt2_mon.h"
  13 
  14 #include <media/dvb_math.h>
  15 
  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},
  21 };
  22 
  23 int cxd2880_tnrdmd_dvbt2_mon_sync_stat(struct cxd2880_tnrdmd
  24                                        *tnr_dmd, u8 *sync_stat,
  25                                        u8 *ts_lock_stat,
  26                                        u8 *unlock_detected)
  27 {
  28         u8 data;
  29         int ret;
  30 
  31         if (!tnr_dmd || !sync_stat || !ts_lock_stat || !unlock_detected)
  32                 return -EINVAL;
  33 
  34         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
  35                 return -EINVAL;
  36 
  37         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2)
  38                 return -EINVAL;
  39 
  40         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  41                                      CXD2880_IO_TGT_DMD,
  42                                      0x00, 0x0b);
  43         if (ret)
  44                 return ret;
  45 
  46         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
  47                                      CXD2880_IO_TGT_DMD,
  48                                      0x10, &data, sizeof(data));
  49         if (ret)
  50                 return ret;
  51 
  52         *sync_stat = data & 0x07;
  53         *ts_lock_stat = ((data & 0x20) ? 1 : 0);
  54         *unlock_detected = ((data & 0x10) ? 1 : 0);
  55 
  56         if (*sync_stat == 0x07)
  57                 return -EAGAIN;
  58 
  59         return 0;
  60 }
  61 
  62 int cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub(struct cxd2880_tnrdmd
  63                                            *tnr_dmd,
  64                                            u8 *sync_stat,
  65                                            u8 *unlock_detected)
  66 {
  67         u8 ts_lock_stat = 0;
  68 
  69         if (!tnr_dmd || !sync_stat || !unlock_detected)
  70                 return -EINVAL;
  71 
  72         if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN)
  73                 return -EINVAL;
  74 
  75         return cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd->diver_sub,
  76                                                   sync_stat,
  77                                                   &ts_lock_stat,
  78                                                   unlock_detected);
  79 }
  80 
  81 int cxd2880_tnrdmd_dvbt2_mon_carrier_offset(struct cxd2880_tnrdmd
  82                                             *tnr_dmd, int *offset)
  83 {
  84         u8 data[4];
  85         u32 ctl_val = 0;
  86         u8 sync_state = 0;
  87         u8 ts_lock = 0;
  88         u8 unlock_detected = 0;
  89         int ret;
  90 
  91         if (!tnr_dmd || !offset)
  92                 return -EINVAL;
  93 
  94         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
  95                 return -EINVAL;
  96 
  97         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2)
  98                 return -EINVAL;
  99 
 100         ret = slvt_freeze_reg(tnr_dmd);
 101         if (ret)
 102                 return ret;
 103 
 104         ret =
 105             cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_state,
 106                                                &ts_lock,
 107                                                &unlock_detected);
 108         if (ret) {
 109                 slvt_unfreeze_reg(tnr_dmd);
 110                 return ret;
 111         }
 112 
 113         if (sync_state != 6) {
 114                 slvt_unfreeze_reg(tnr_dmd);
 115                 return -EAGAIN;
 116         }
 117 
 118         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
 119                                      CXD2880_IO_TGT_DMD,
 120                                      0x00, 0x0b);
 121         if (ret) {
 122                 slvt_unfreeze_reg(tnr_dmd);
 123                 return ret;
 124         }
 125 
 126         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
 127                                      CXD2880_IO_TGT_DMD,
 128                                      0x30, data, sizeof(data));
 129         if (ret) {
 130                 slvt_unfreeze_reg(tnr_dmd);
 131                 return ret;
 132         }
 133 
 134         slvt_unfreeze_reg(tnr_dmd);
 135 
 136         ctl_val =
 137             ((data[0] & 0x0f) << 24) | (data[1] << 16) | (data[2] << 8)
 138             | (data[3]);
 139         *offset = cxd2880_convert2s_complement(ctl_val, 28);
 140 
 141         switch (tnr_dmd->bandwidth) {
 142         case CXD2880_DTV_BW_1_7_MHZ:
 143                 *offset = -1 * ((*offset) / 582);
 144                 break;
 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);
 150                 break;
 151         default:
 152                 return -EINVAL;
 153         }
 154 
 155         return 0;
 156 }
 157 
 158 int cxd2880_tnrdmd_dvbt2_mon_carrier_offset_sub(struct
 159                                                 cxd2880_tnrdmd
 160                                                 *tnr_dmd,
 161                                                 int *offset)
 162 {
 163         if (!tnr_dmd || !offset)
 164                 return -EINVAL;
 165 
 166         if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN)
 167                 return -EINVAL;
 168 
 169         return cxd2880_tnrdmd_dvbt2_mon_carrier_offset(tnr_dmd->diver_sub,
 170                                                        offset);
 171 }
 172 
 173 int cxd2880_tnrdmd_dvbt2_mon_l1_pre(struct cxd2880_tnrdmd *tnr_dmd,
 174                                     struct cxd2880_dvbt2_l1pre
 175                                     *l1_pre)
 176 {
 177         u8 data[37];
 178         u8 sync_state = 0;
 179         u8 ts_lock = 0;
 180         u8 unlock_detected = 0;
 181         u8 version = 0;
 182         enum cxd2880_dvbt2_profile profile;
 183         int ret;
 184 
 185         if (!tnr_dmd || !l1_pre)
 186                 return -EINVAL;
 187 
 188         if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
 189                 return -EINVAL;
 190 
 191         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
 192                 return -EINVAL;
 193 
 194         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2)
 195                 return -EINVAL;
 196 
 197         ret = slvt_freeze_reg(tnr_dmd);
 198         if (ret)
 199                 return ret;
 200 
 201         ret =
 202             cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_state,
 203                                                &ts_lock,
 204                                                &unlock_detected);
 205         if (ret) {
 206                 slvt_unfreeze_reg(tnr_dmd);
 207                 return ret;
 208         }
 209 
 210         if (sync_state < 5) {
 211                 if (tnr_dmd->diver_mode ==
 212                     CXD2880_TNRDMD_DIVERMODE_MAIN) {
 213                         ret =
 214                             cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub
 215                             (tnr_dmd, &sync_state, &unlock_detected);
 216                         if (ret) {
 217                                 slvt_unfreeze_reg(tnr_dmd);
 218                                 return ret;
 219                         }
 220 
 221                         if (sync_state < 5) {
 222                                 slvt_unfreeze_reg(tnr_dmd);
 223                                 return -EAGAIN;
 224                         }
 225                 } else {
 226                         slvt_unfreeze_reg(tnr_dmd);
 227                         return -EAGAIN;
 228                 }
 229         }
 230 
 231         ret = cxd2880_tnrdmd_dvbt2_mon_profile(tnr_dmd, &profile);
 232         if (ret) {
 233                 slvt_unfreeze_reg(tnr_dmd);
 234                 return ret;
 235         }
 236 
 237         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
 238                                      CXD2880_IO_TGT_DMD,
 239                                      0x00, 0x0b);
 240         if (ret) {
 241                 slvt_unfreeze_reg(tnr_dmd);
 242                 return ret;
 243         }
 244 
 245         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
 246                                      CXD2880_IO_TGT_DMD,
 247                                      0x61, data, sizeof(data));
 248         if (ret) {
 249                 slvt_unfreeze_reg(tnr_dmd);
 250                 return ret;
 251         }
 252         slvt_unfreeze_reg(tnr_dmd);
 253 
 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);
 261         l1_pre->mod =
 262             (enum cxd2880_dvbt2_l1post_constell)(data[7] & 0x0f);
 263         l1_pre->cr = (enum cxd2880_dvbt2_l1post_cr)(data[8] & 0x03);
 264         l1_pre->fec =
 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];
 296 
 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;
 301                         break;
 302                 case CXD2880_DVBT2_BASE_S2_M2K_G_ANY:
 303                         l1_pre->fft_mode = CXD2880_DVBT2_M2K;
 304                         break;
 305                 case CXD2880_DVBT2_BASE_S2_M4K_G_ANY:
 306                         l1_pre->fft_mode = CXD2880_DVBT2_M4K;
 307                         break;
 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;
 311                         break;
 312                 case CXD2880_DVBT2_BASE_S2_M16K_G_ANY:
 313                         l1_pre->fft_mode = CXD2880_DVBT2_M16K;
 314                         break;
 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;
 318                         break;
 319                 default:
 320                         return -EAGAIN;
 321                 }
 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;
 326                         break;
 327                 case CXD2880_DVBT2_LITE_S2_M4K_G_ANY:
 328                         l1_pre->fft_mode = CXD2880_DVBT2_M4K;
 329                         break;
 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;
 333                         break;
 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;
 337                         break;
 338                 default:
 339                         return -EAGAIN;
 340                 }
 341         } else {
 342                 return -EAGAIN;
 343         }
 344 
 345         l1_pre->mixed = l1_pre->s2 & 0x01;
 346 
 347         return ret;
 348 }
 349 
 350 int cxd2880_tnrdmd_dvbt2_mon_version(struct cxd2880_tnrdmd
 351                                      *tnr_dmd,
 352                                      enum cxd2880_dvbt2_version
 353                                      *ver)
 354 {
 355         u8 data[2];
 356         u8 sync_state = 0;
 357         u8 ts_lock = 0;
 358         u8 unlock_detected = 0;
 359         u8 version = 0;
 360         int ret;
 361 
 362         if (!tnr_dmd || !ver)
 363                 return -EINVAL;
 364 
 365         if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
 366                 return -EINVAL;
 367 
 368         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
 369                 return -EINVAL;
 370 
 371         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2)
 372                 return -EINVAL;
 373 
 374         ret = slvt_freeze_reg(tnr_dmd);
 375         if (ret)
 376                 return ret;
 377 
 378         ret =
 379             cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_state,
 380                                                &ts_lock,
 381                                                &unlock_detected);
 382         if (ret) {
 383                 slvt_unfreeze_reg(tnr_dmd);
 384                 return ret;
 385         }
 386 
 387         if (sync_state < 5) {
 388                 if (tnr_dmd->diver_mode ==
 389                     CXD2880_TNRDMD_DIVERMODE_MAIN) {
 390                         ret =
 391                             cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub
 392                             (tnr_dmd, &sync_state, &unlock_detected);
 393                         if (ret) {
 394                                 slvt_unfreeze_reg(tnr_dmd);
 395                                 return ret;
 396                         }
 397 
 398                         if (sync_state < 5) {
 399                                 slvt_unfreeze_reg(tnr_dmd);
 400                                 return -EAGAIN;
 401                         }
 402                 } else {
 403                         slvt_unfreeze_reg(tnr_dmd);
 404                         return -EAGAIN;
 405                 }
 406         }
 407 
 408         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
 409                                      CXD2880_IO_TGT_DMD,
 410                                      0x00, 0x0b);
 411         if (ret) {
 412                 slvt_unfreeze_reg(tnr_dmd);
 413                 return ret;
 414         }
 415 
 416         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
 417                                      CXD2880_IO_TGT_DMD,
 418                                      0x80, data, sizeof(data));
 419         if (ret) {
 420                 slvt_unfreeze_reg(tnr_dmd);
 421                 return ret;
 422         }
 423 
 424         slvt_unfreeze_reg(tnr_dmd);
 425 
 426         version = ((data[0] & 0x03) << 2);
 427         version |= ((data[1] & 0xc0) >> 6);
 428         *ver = (enum cxd2880_dvbt2_version)version;
 429 
 430         return ret;
 431 }
 432 
 433 int cxd2880_tnrdmd_dvbt2_mon_ofdm(struct cxd2880_tnrdmd *tnr_dmd,
 434                                   struct cxd2880_dvbt2_ofdm *ofdm)
 435 {
 436         u8 data[5];
 437         u8 sync_state = 0;
 438         u8 ts_lock = 0;
 439         u8 unlock_detected = 0;
 440         int ret;
 441 
 442         if (!tnr_dmd || !ofdm)
 443                 return -EINVAL;
 444 
 445         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
 446                 return -EINVAL;
 447 
 448         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2)
 449                 return -EINVAL;
 450 
 451         ret = slvt_freeze_reg(tnr_dmd);
 452         if (ret)
 453                 return ret;
 454 
 455         ret =
 456             cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_state,
 457                                                &ts_lock,
 458                                                &unlock_detected);
 459         if (ret) {
 460                 slvt_unfreeze_reg(tnr_dmd);
 461                 return ret;
 462         }
 463 
 464         if (sync_state != 6) {
 465                 slvt_unfreeze_reg(tnr_dmd);
 466 
 467                 ret = -EAGAIN;
 468 
 469                 if (tnr_dmd->diver_mode ==
 470                     CXD2880_TNRDMD_DIVERMODE_MAIN)
 471                         ret =
 472                             cxd2880_tnrdmd_dvbt2_mon_ofdm(tnr_dmd->diver_sub,
 473                                                           ofdm);
 474 
 475                 return ret;
 476         }
 477 
 478         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
 479                                      CXD2880_IO_TGT_DMD,
 480                                      0x00, 0x0b);
 481         if (ret) {
 482                 slvt_unfreeze_reg(tnr_dmd);
 483                 return ret;
 484         }
 485 
 486         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
 487                                      CXD2880_IO_TGT_DMD,
 488                                      0x1d, data, sizeof(data));
 489         if (ret) {
 490                 slvt_unfreeze_reg(tnr_dmd);
 491                 return ret;
 492         }
 493 
 494         slvt_unfreeze_reg(tnr_dmd);
 495 
 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];
 504 
 505         return 0;
 506 }
 507 
 508 int cxd2880_tnrdmd_dvbt2_mon_data_plps(struct cxd2880_tnrdmd
 509                                        *tnr_dmd, u8 *plp_ids,
 510                                        u8 *num_plps)
 511 {
 512         u8 l1_post_ok = 0;
 513         int ret;
 514 
 515         if (!tnr_dmd || !num_plps)
 516                 return -EINVAL;
 517 
 518         if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
 519                 return -EINVAL;
 520 
 521         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
 522                 return -EINVAL;
 523 
 524         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2)
 525                 return -EINVAL;
 526 
 527         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
 528                                      CXD2880_IO_TGT_DMD,
 529                                      0x00, 0x0b);
 530         if (ret)
 531                 return ret;
 532 
 533         ret = slvt_freeze_reg(tnr_dmd);
 534         if (ret)
 535                 return ret;
 536 
 537         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
 538                                      CXD2880_IO_TGT_DMD,
 539                                      0x86, &l1_post_ok, 1);
 540         if (ret) {
 541                 slvt_unfreeze_reg(tnr_dmd);
 542                 return ret;
 543         }
 544 
 545         if (!(l1_post_ok & 0x01)) {
 546                 slvt_unfreeze_reg(tnr_dmd);
 547                 return -EAGAIN;
 548         }
 549 
 550         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
 551                                      CXD2880_IO_TGT_DMD,
 552                                      0xc1, num_plps, 1);
 553         if (ret) {
 554                 slvt_unfreeze_reg(tnr_dmd);
 555                 return ret;
 556         }
 557 
 558         if (*num_plps == 0) {
 559                 slvt_unfreeze_reg(tnr_dmd);
 560                 return -EINVAL;
 561         }
 562 
 563         if (!plp_ids) {
 564                 slvt_unfreeze_reg(tnr_dmd);
 565                 return 0;
 566         }
 567 
 568         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
 569                                      CXD2880_IO_TGT_DMD,
 570                                      0xc2,
 571                                      plp_ids,
 572                                      ((*num_plps > 62) ?
 573                                      62 : *num_plps));
 574         if (ret) {
 575                 slvt_unfreeze_reg(tnr_dmd);
 576                 return ret;
 577         }
 578 
 579         if (*num_plps > 62) {
 580                 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
 581                                              CXD2880_IO_TGT_DMD,
 582                                              0x00, 0x0c);
 583                 if (ret) {
 584                         slvt_unfreeze_reg(tnr_dmd);
 585                         return ret;
 586                 }
 587 
 588                 ret = tnr_dmd->io->read_regs(tnr_dmd->io,
 589                                              CXD2880_IO_TGT_DMD,
 590                                              0x10, plp_ids + 62,
 591                                              *num_plps - 62);
 592                 if (ret) {
 593                         slvt_unfreeze_reg(tnr_dmd);
 594                         return ret;
 595                 }
 596         }
 597 
 598         slvt_unfreeze_reg(tnr_dmd);
 599 
 600         return 0;
 601 }
 602 
 603 int cxd2880_tnrdmd_dvbt2_mon_active_plp(struct cxd2880_tnrdmd
 604                                         *tnr_dmd,
 605                                         enum
 606                                         cxd2880_dvbt2_plp_btype
 607                                         type,
 608                                         struct cxd2880_dvbt2_plp
 609                                         *plp_info)
 610 {
 611         u8 data[20];
 612         u8 addr = 0;
 613         u8 index = 0;
 614         u8 l1_post_ok = 0;
 615         int ret;
 616 
 617         if (!tnr_dmd || !plp_info)
 618                 return -EINVAL;
 619 
 620         if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
 621                 return -EINVAL;
 622 
 623         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
 624                 return -EINVAL;
 625 
 626         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2)
 627                 return -EINVAL;
 628 
 629         ret = slvt_freeze_reg(tnr_dmd);
 630         if (ret)
 631                 return ret;
 632 
 633         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
 634                                      CXD2880_IO_TGT_DMD,
 635                                      0x00, 0x0b);
 636         if (ret) {
 637                 slvt_unfreeze_reg(tnr_dmd);
 638                 return ret;
 639         }
 640 
 641         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
 642                                      CXD2880_IO_TGT_DMD,
 643                                      0x86, &l1_post_ok, 1);
 644         if (ret) {
 645                 slvt_unfreeze_reg(tnr_dmd);
 646                 return ret;
 647         }
 648 
 649         if (!l1_post_ok) {
 650                 slvt_unfreeze_reg(tnr_dmd);
 651                 return -EAGAIN;
 652         }
 653 
 654         if (type == CXD2880_DVBT2_PLP_COMMON)
 655                 addr = 0xa9;
 656         else
 657                 addr = 0x96;
 658 
 659         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
 660                                      CXD2880_IO_TGT_DMD,
 661                                      addr, data, sizeof(data));
 662         if (ret) {
 663                 slvt_unfreeze_reg(tnr_dmd);
 664                 return ret;
 665         }
 666 
 667         slvt_unfreeze_reg(tnr_dmd);
 668 
 669         if (type == CXD2880_DVBT2_PLP_COMMON && !data[13])
 670                 return -EAGAIN;
 671 
 672         plp_info->id = data[index++];
 673         plp_info->type =
 674             (enum cxd2880_dvbt2_plp_type)(data[index++] & 0x07);
 675         plp_info->payload =
 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++];
 681         plp_info->plp_cr =
 682             (enum cxd2880_dvbt2_plp_code_rate)(data[index++] & 0x07);
 683         plp_info->constell =
 684             (enum cxd2880_dvbt2_plp_constell)(data[index++] & 0x07);
 685         plp_info->rot = data[index++] & 0x01;
 686         plp_info->fec =
 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;
 693 
 694         plp_info->in_band_a_flag = data[index++] & 0x01;
 695         plp_info->rsvd = data[index++] << 8;
 696         plp_info->rsvd |= data[index++];
 697 
 698         plp_info->in_band_b_flag =
 699             (plp_info->rsvd & 0x8000) >> 15;
 700         plp_info->plp_mode =
 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;
 705 
 706         return 0;
 707 }
 708 
 709 int cxd2880_tnrdmd_dvbt2_mon_data_plp_error(struct cxd2880_tnrdmd
 710                                             *tnr_dmd,
 711                                             u8 *plp_error)
 712 {
 713         u8 data;
 714         int ret;
 715 
 716         if (!tnr_dmd || !plp_error)
 717                 return -EINVAL;
 718 
 719         if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
 720                 return -EINVAL;
 721 
 722         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
 723                 return -EINVAL;
 724 
 725         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2)
 726                 return -EINVAL;
 727 
 728         ret = slvt_freeze_reg(tnr_dmd);
 729         if (ret)
 730                 return ret;
 731 
 732         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
 733                                      CXD2880_IO_TGT_DMD,
 734                                      0x00, 0x0b);
 735         if (ret) {
 736                 slvt_unfreeze_reg(tnr_dmd);
 737                 return ret;
 738         }
 739 
 740         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
 741                                      CXD2880_IO_TGT_DMD,
 742                                      0x86, &data, 1);
 743         if (ret) {
 744                 slvt_unfreeze_reg(tnr_dmd);
 745                 return ret;
 746         }
 747 
 748         if ((data & 0x01) == 0x00) {
 749                 slvt_unfreeze_reg(tnr_dmd);
 750                 return -EAGAIN;
 751         }
 752 
 753         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
 754                                      CXD2880_IO_TGT_DMD,
 755                                      0xc0, &data, 1);
 756         if (ret) {
 757                 slvt_unfreeze_reg(tnr_dmd);
 758                 return ret;
 759         }
 760 
 761         slvt_unfreeze_reg(tnr_dmd);
 762 
 763         *plp_error = data & 0x01;
 764 
 765         return 0;
 766 }
 767 
 768 int cxd2880_tnrdmd_dvbt2_mon_l1_change(struct cxd2880_tnrdmd
 769                                        *tnr_dmd, u8 *l1_change)
 770 {
 771         u8 data;
 772         u8 sync_state = 0;
 773         u8 ts_lock = 0;
 774         u8 unlock_detected = 0;
 775         int ret;
 776 
 777         if (!tnr_dmd || !l1_change)
 778                 return -EINVAL;
 779 
 780         if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
 781                 return -EINVAL;
 782 
 783         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
 784                 return -EINVAL;
 785 
 786         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2)
 787                 return -EINVAL;
 788 
 789         ret = slvt_freeze_reg(tnr_dmd);
 790         if (ret)
 791                 return ret;
 792 
 793         ret =
 794             cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_state,
 795                                                &ts_lock,
 796                                                &unlock_detected);
 797         if (ret) {
 798                 slvt_unfreeze_reg(tnr_dmd);
 799                 return ret;
 800         }
 801 
 802         if (sync_state < 5) {
 803                 if (tnr_dmd->diver_mode ==
 804                     CXD2880_TNRDMD_DIVERMODE_MAIN) {
 805                         ret =
 806                             cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub
 807                             (tnr_dmd, &sync_state, &unlock_detected);
 808                         if (ret) {
 809                                 slvt_unfreeze_reg(tnr_dmd);
 810                                 return ret;
 811                         }
 812 
 813                         if (sync_state < 5) {
 814                                 slvt_unfreeze_reg(tnr_dmd);
 815                                 return -EAGAIN;
 816                         }
 817                 } else {
 818                         slvt_unfreeze_reg(tnr_dmd);
 819                         return -EAGAIN;
 820                 }
 821         }
 822 
 823         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
 824                                      CXD2880_IO_TGT_DMD,
 825                                      0x00, 0x0b);
 826         if (ret) {
 827                 slvt_unfreeze_reg(tnr_dmd);
 828                 return ret;
 829         }
 830 
 831         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
 832                                      CXD2880_IO_TGT_DMD,
 833                                      0x5f, &data, sizeof(data));
 834         if (ret) {
 835                 slvt_unfreeze_reg(tnr_dmd);
 836                 return ret;
 837         }
 838 
 839         *l1_change = data & 0x01;
 840         if (*l1_change) {
 841                 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
 842                                              CXD2880_IO_TGT_DMD,
 843                                              0x00, 0x22);
 844                 if (ret) {
 845                         slvt_unfreeze_reg(tnr_dmd);
 846                         return ret;
 847                 }
 848 
 849                 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
 850                                              CXD2880_IO_TGT_DMD,
 851                                              0x16, 0x01);
 852                 if (ret) {
 853                         slvt_unfreeze_reg(tnr_dmd);
 854                         return ret;
 855                 }
 856         }
 857         slvt_unfreeze_reg(tnr_dmd);
 858 
 859         return 0;
 860 }
 861 
 862 int cxd2880_tnrdmd_dvbt2_mon_l1_post(struct cxd2880_tnrdmd
 863                                      *tnr_dmd,
 864                                      struct cxd2880_dvbt2_l1post
 865                                      *l1_post)
 866 {
 867         u8 data[16];
 868         int ret;
 869 
 870         if (!tnr_dmd || !l1_post)
 871                 return -EINVAL;
 872 
 873         if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
 874                 return -EINVAL;
 875 
 876         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
 877                 return -EINVAL;
 878 
 879         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2)
 880                 return -EINVAL;
 881 
 882         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
 883                                      CXD2880_IO_TGT_DMD,
 884                                      0x00, 0x0b);
 885         if (ret)
 886                 return ret;
 887 
 888         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
 889                                      CXD2880_IO_TGT_DMD,
 890                                      0x86, data, sizeof(data));
 891         if (ret)
 892                 return ret;
 893 
 894         if (!(data[0] & 0x01))
 895                 return -EAGAIN;
 896 
 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];
 912 
 913         return 0;
 914 }
 915 
 916 int cxd2880_tnrdmd_dvbt2_mon_bbheader(struct cxd2880_tnrdmd
 917                                       *tnr_dmd,
 918                                       enum cxd2880_dvbt2_plp_btype
 919                                       type,
 920                                       struct cxd2880_dvbt2_bbheader
 921                                       *bbheader)
 922 {
 923         u8 sync_state = 0;
 924         u8 ts_lock = 0;
 925         u8 unlock_detected = 0;
 926         u8 data[14];
 927         u8 addr = 0;
 928         int ret;
 929 
 930         if (!tnr_dmd || !bbheader)
 931                 return -EINVAL;
 932 
 933         if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
 934                 return -EINVAL;
 935 
 936         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
 937                 return -EINVAL;
 938 
 939         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2)
 940                 return -EINVAL;
 941 
 942         ret = slvt_freeze_reg(tnr_dmd);
 943         if (ret)
 944                 return ret;
 945 
 946         ret =
 947             cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_state,
 948                                                        &ts_lock,
 949                                                        &unlock_detected);
 950         if (ret) {
 951                 slvt_unfreeze_reg(tnr_dmd);
 952                 return ret;
 953         }
 954 
 955         if (!ts_lock) {
 956                 slvt_unfreeze_reg(tnr_dmd);
 957                 return -EAGAIN;
 958         }
 959 
 960         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
 961                                      CXD2880_IO_TGT_DMD,
 962                                      0x00, 0x0b);
 963         if (ret) {
 964                 slvt_unfreeze_reg(tnr_dmd);
 965                 return ret;
 966         }
 967 
 968         if (type == CXD2880_DVBT2_PLP_COMMON) {
 969                 u8 l1_post_ok;
 970                 u8 data;
 971 
 972                 ret = tnr_dmd->io->read_regs(tnr_dmd->io,
 973                                              CXD2880_IO_TGT_DMD,
 974                                              0x86, &l1_post_ok, 1);
 975                 if (ret) {
 976                         slvt_unfreeze_reg(tnr_dmd);
 977                         return ret;
 978                 }
 979 
 980                 if (!(l1_post_ok & 0x01)) {
 981                         slvt_unfreeze_reg(tnr_dmd);
 982                         return -EAGAIN;
 983                 }
 984 
 985                 ret = tnr_dmd->io->read_regs(tnr_dmd->io,
 986                                              CXD2880_IO_TGT_DMD,
 987                                              0xb6, &data, 1);
 988                 if (ret) {
 989                         slvt_unfreeze_reg(tnr_dmd);
 990                         return ret;
 991                 }
 992 
 993                 if (data == 0) {
 994                         slvt_unfreeze_reg(tnr_dmd);
 995                         return -EAGAIN;
 996                 }
 997         }
 998 
 999         if (type == CXD2880_DVBT2_PLP_COMMON)
1000                 addr = 0x51;
1001         else
1002                 addr = 0x42;
1003 
1004         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
1005                                      CXD2880_IO_TGT_DMD,
1006                                      addr, data, sizeof(data));
1007         if (ret) {
1008                 slvt_unfreeze_reg(tnr_dmd);
1009                 return ret;
1010         }
1011 
1012         slvt_unfreeze_reg(tnr_dmd);
1013 
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;
1022 
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];
1028 
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];
1033                 bbheader->issy = 0;
1034         } else {
1035                 bbheader->user_packet_length = 0;
1036                 bbheader->sync_byte = 0;
1037                 bbheader->issy =
1038                     (data[11] << 16) | (data[12] << 8) | data[13];
1039         }
1040 
1041         return 0;
1042 }
1043 
1044 int cxd2880_tnrdmd_dvbt2_mon_in_bandb_ts_rate(struct cxd2880_tnrdmd
1045                                               *tnr_dmd,
1046                                               enum
1047                                               cxd2880_dvbt2_plp_btype
1048                                               type,
1049                                               u32 *ts_rate_bps)
1050 {
1051         u8 sync_state = 0;
1052         u8 ts_lock = 0;
1053         u8 unlock_detected = 0;
1054         u8 l1_post_ok = 0;
1055         u8 data[4];
1056         u8 addr = 0;
1057 
1058         int ret;
1059 
1060         if (!tnr_dmd || !ts_rate_bps)
1061                 return -EINVAL;
1062 
1063         if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
1064                 return -EINVAL;
1065 
1066         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
1067                 return -EINVAL;
1068 
1069         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2)
1070                 return -EINVAL;
1071 
1072         ret = slvt_freeze_reg(tnr_dmd);
1073         if (ret)
1074                 return ret;
1075 
1076         ret =
1077             cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_state,
1078                                                &ts_lock,
1079                                                &unlock_detected);
1080         if (ret) {
1081                 slvt_unfreeze_reg(tnr_dmd);
1082                 return ret;
1083         }
1084 
1085         if (!ts_lock) {
1086                 slvt_unfreeze_reg(tnr_dmd);
1087                 return -EAGAIN;
1088         }
1089 
1090         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
1091                                      CXD2880_IO_TGT_DMD,
1092                                      0x00, 0x0b);
1093         if (ret) {
1094                 slvt_unfreeze_reg(tnr_dmd);
1095                 return ret;
1096         }
1097 
1098         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
1099                                      CXD2880_IO_TGT_DMD,
1100                                      0x86, &l1_post_ok, 1);
1101         if (ret) {
1102                 slvt_unfreeze_reg(tnr_dmd);
1103                 return ret;
1104         }
1105 
1106         if (!(l1_post_ok & 0x01)) {
1107                 slvt_unfreeze_reg(tnr_dmd);
1108                 return -EAGAIN;
1109         }
1110 
1111         if (type == CXD2880_DVBT2_PLP_COMMON)
1112                 addr = 0xba;
1113         else
1114                 addr = 0xa7;
1115 
1116         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
1117                                      CXD2880_IO_TGT_DMD,
1118                                      addr, &data[0], 1);
1119         if (ret) {
1120                 slvt_unfreeze_reg(tnr_dmd);
1121                 return ret;
1122         }
1123 
1124         if ((data[0] & 0x80) == 0x00) {
1125                 slvt_unfreeze_reg(tnr_dmd);
1126                 return -EAGAIN;
1127         }
1128 
1129         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
1130                                      CXD2880_IO_TGT_DMD,
1131                                      0x00, 0x25);
1132         if (ret) {
1133                 slvt_unfreeze_reg(tnr_dmd);
1134                 return ret;
1135         }
1136 
1137         if (type == CXD2880_DVBT2_PLP_COMMON)
1138                 addr = 0xa6;
1139         else
1140                 addr = 0xaa;
1141 
1142         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
1143                                      CXD2880_IO_TGT_DMD,
1144                                      addr, &data[0], 4);
1145         if (ret) {
1146                 slvt_unfreeze_reg(tnr_dmd);
1147                 return ret;
1148         }
1149 
1150         *ts_rate_bps = ((data[0] & 0x07) << 24) | (data[1] << 16) |
1151                        (data[2] << 8) | data[3];
1152 
1153         return 0;
1154 }
1155 
1156 int cxd2880_tnrdmd_dvbt2_mon_spectrum_sense(struct cxd2880_tnrdmd
1157                                             *tnr_dmd,
1158                                             enum
1159                                             cxd2880_tnrdmd_spectrum_sense
1160                                             *sense)
1161 {
1162         u8 sync_state = 0;
1163         u8 ts_lock = 0;
1164         u8 early_unlock = 0;
1165         u8 data = 0;
1166         int ret;
1167 
1168         if (!tnr_dmd || !sense)
1169                 return -EINVAL;
1170 
1171         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
1172                 return -EINVAL;
1173 
1174         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2)
1175                 return -EINVAL;
1176 
1177         ret = slvt_freeze_reg(tnr_dmd);
1178         if (ret)
1179                 return ret;
1180 
1181         ret =
1182             cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_state, &ts_lock,
1183                                                &early_unlock);
1184         if (ret) {
1185                 slvt_unfreeze_reg(tnr_dmd);
1186                 return ret;
1187         }
1188 
1189         if (sync_state != 6) {
1190                 slvt_unfreeze_reg(tnr_dmd);
1191 
1192                 ret = -EAGAIN;
1193 
1194                 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN)
1195                         ret =
1196                             cxd2880_tnrdmd_dvbt2_mon_spectrum_sense(tnr_dmd->diver_sub,
1197                                                                     sense);
1198 
1199                 return ret;
1200         }
1201 
1202         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
1203                                      CXD2880_IO_TGT_DMD,
1204                                      0x00, 0x0b);
1205         if (ret) {
1206                 slvt_unfreeze_reg(tnr_dmd);
1207                 return ret;
1208         }
1209 
1210         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
1211                                      CXD2880_IO_TGT_DMD,
1212                                      0x2f, &data, sizeof(data));
1213         if (ret) {
1214                 slvt_unfreeze_reg(tnr_dmd);
1215                 return ret;
1216         }
1217 
1218         slvt_unfreeze_reg(tnr_dmd);
1219 
1220         *sense =
1221             (data & 0x01) ? CXD2880_TNRDMD_SPECTRUM_INV :
1222             CXD2880_TNRDMD_SPECTRUM_NORMAL;
1223 
1224         return 0;
1225 }
1226 
1227 static int dvbt2_read_snr_reg(struct cxd2880_tnrdmd *tnr_dmd,
1228                               u16 *reg_value)
1229 {
1230         u8 sync_state = 0;
1231         u8 ts_lock = 0;
1232         u8 unlock_detected = 0;
1233         u8 data[2];
1234         int ret;
1235 
1236         if (!tnr_dmd || !reg_value)
1237                 return -EINVAL;
1238 
1239         ret = slvt_freeze_reg(tnr_dmd);
1240         if (ret)
1241                 return ret;
1242 
1243         ret =
1244             cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_state,
1245                                                &ts_lock,
1246                                                &unlock_detected);
1247         if (ret) {
1248                 slvt_unfreeze_reg(tnr_dmd);
1249                 return ret;
1250         }
1251 
1252         if (sync_state != 6) {
1253                 slvt_unfreeze_reg(tnr_dmd);
1254                 return -EAGAIN;
1255         }
1256 
1257         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
1258                                      CXD2880_IO_TGT_DMD,
1259                                      0x00, 0x0b);
1260         if (ret) {
1261                 slvt_unfreeze_reg(tnr_dmd);
1262                 return ret;
1263         }
1264 
1265         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
1266                                      CXD2880_IO_TGT_DMD,
1267                                      0x13, data, sizeof(data));
1268         if (ret) {
1269                 slvt_unfreeze_reg(tnr_dmd);
1270                 return ret;
1271         }
1272 
1273         slvt_unfreeze_reg(tnr_dmd);
1274 
1275         *reg_value = (data[0] << 8) | data[1];
1276 
1277         return ret;
1278 }
1279 
1280 static int dvbt2_calc_snr(struct cxd2880_tnrdmd *tnr_dmd,
1281                           u32 reg_value, int *snr)
1282 {
1283         if (!tnr_dmd || !snr)
1284                 return -EINVAL;
1285 
1286         if (reg_value == 0)
1287                 return -EAGAIN;
1288 
1289         if (reg_value > 10876)
1290                 reg_value = 10876;
1291 
1292         *snr = intlog10(reg_value) - intlog10(12600 - reg_value);
1293         *snr = (*snr + 839) / 1678 + 32000;
1294 
1295         return 0;
1296 }
1297 
1298 int cxd2880_tnrdmd_dvbt2_mon_snr(struct cxd2880_tnrdmd *tnr_dmd,
1299                                  int *snr)
1300 {
1301         u16 reg_value = 0;
1302         int ret;
1303 
1304         if (!tnr_dmd || !snr)
1305                 return -EINVAL;
1306 
1307         *snr = -1000 * 1000;
1308 
1309         if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
1310                 return -EINVAL;
1311 
1312         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
1313                 return -EINVAL;
1314 
1315         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2)
1316                 return -EINVAL;
1317 
1318         if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) {
1319                 ret = dvbt2_read_snr_reg(tnr_dmd, &reg_value);
1320                 if (ret)
1321                         return ret;
1322 
1323                 ret = dvbt2_calc_snr(tnr_dmd, reg_value, snr);
1324         } else {
1325                 int snr_main = 0;
1326                 int snr_sub = 0;
1327 
1328                 ret =
1329                     cxd2880_tnrdmd_dvbt2_mon_snr_diver(tnr_dmd, snr, &snr_main,
1330                                                        &snr_sub);
1331         }
1332 
1333         return ret;
1334 }
1335 
1336 int cxd2880_tnrdmd_dvbt2_mon_snr_diver(struct cxd2880_tnrdmd
1337                                        *tnr_dmd, int *snr,
1338                                        int *snr_main, int *snr_sub)
1339 {
1340         u16 reg_value = 0;
1341         u32 reg_value_sum = 0;
1342         int ret;
1343 
1344         if (!tnr_dmd || !snr || !snr_main || !snr_sub)
1345                 return -EINVAL;
1346 
1347         *snr = -1000 * 1000;
1348         *snr_main = -1000 * 1000;
1349         *snr_sub = -1000 * 1000;
1350 
1351         if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN)
1352                 return -EINVAL;
1353 
1354         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
1355                 return -EINVAL;
1356 
1357         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2)
1358                 return -EINVAL;
1359 
1360         ret = dvbt2_read_snr_reg(tnr_dmd, &reg_value);
1361         if (!ret) {
1362                 ret = dvbt2_calc_snr(tnr_dmd, reg_value, snr_main);
1363                 if (ret)
1364                         reg_value = 0;
1365         } else if (ret == -EAGAIN) {
1366                 reg_value = 0;
1367         } else {
1368                 return ret;
1369         }
1370 
1371         reg_value_sum += reg_value;
1372 
1373         ret = dvbt2_read_snr_reg(tnr_dmd->diver_sub, &reg_value);
1374         if (!ret) {
1375                 ret = dvbt2_calc_snr(tnr_dmd->diver_sub, reg_value, snr_sub);
1376                 if (ret)
1377                         reg_value = 0;
1378         } else if (ret == -EAGAIN) {
1379                 reg_value = 0;
1380         } else {
1381                 return ret;
1382         }
1383 
1384         reg_value_sum += reg_value;
1385 
1386         return dvbt2_calc_snr(tnr_dmd, reg_value_sum, snr);
1387 }
1388 
1389 int cxd2880_tnrdmd_dvbt2_mon_packet_error_number(struct
1390                                                  cxd2880_tnrdmd
1391                                                  *tnr_dmd,
1392                                                  u32 *pen)
1393 {
1394         int ret;
1395         u8 data[3];
1396 
1397         if (!tnr_dmd || !pen)
1398                 return -EINVAL;
1399 
1400         if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
1401                 return -EINVAL;
1402 
1403         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
1404                 return -EINVAL;
1405 
1406         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2)
1407                 return -EINVAL;
1408 
1409         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
1410                                      CXD2880_IO_TGT_DMD,
1411                                      0x00, 0x0b);
1412         if (ret)
1413                 return ret;
1414 
1415         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
1416                                      CXD2880_IO_TGT_DMD,
1417                                      0x39, data, sizeof(data));
1418         if (ret)
1419                 return ret;
1420 
1421         if (!(data[0] & 0x01))
1422                 return -EAGAIN;
1423 
1424         *pen = ((data[1] << 8) | data[2]);
1425 
1426         return ret;
1427 }
1428 
1429 int cxd2880_tnrdmd_dvbt2_mon_sampling_offset(struct cxd2880_tnrdmd
1430                                              *tnr_dmd, int *ppm)
1431 {
1432         u8 ctl_val_reg[5];
1433         u8 nominal_rate_reg[5];
1434         u32 trl_ctl_val = 0;
1435         u32 trcg_nominal_rate = 0;
1436         int num;
1437         int den;
1438         int ret;
1439         u8 sync_state = 0;
1440         u8 ts_lock = 0;
1441         u8 unlock_detected = 0;
1442         s8 diff_upper = 0;
1443 
1444         if (!tnr_dmd || !ppm)
1445                 return -EINVAL;
1446 
1447         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
1448                 return -EINVAL;
1449 
1450         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2)
1451                 return -EINVAL;
1452 
1453         ret = slvt_freeze_reg(tnr_dmd);
1454         if (ret)
1455                 return ret;
1456 
1457         ret =
1458             cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_state,
1459                                                &ts_lock,
1460                                                &unlock_detected);
1461         if (ret) {
1462                 slvt_unfreeze_reg(tnr_dmd);
1463                 return ret;
1464         }
1465 
1466         if (sync_state != 6) {
1467                 slvt_unfreeze_reg(tnr_dmd);
1468                 return -EAGAIN;
1469         }
1470 
1471         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
1472                                      CXD2880_IO_TGT_DMD,
1473                                      0x00, 0x0b);
1474         if (ret) {
1475                 slvt_unfreeze_reg(tnr_dmd);
1476                 return ret;
1477         }
1478 
1479         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
1480                                      CXD2880_IO_TGT_DMD,
1481                                      0x34, ctl_val_reg,
1482                                      sizeof(ctl_val_reg));
1483         if (ret) {
1484                 slvt_unfreeze_reg(tnr_dmd);
1485                 return ret;
1486         }
1487 
1488         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
1489                                      CXD2880_IO_TGT_DMD,
1490                                      0x00, 0x04);
1491         if (ret) {
1492                 slvt_unfreeze_reg(tnr_dmd);
1493                 return ret;
1494         }
1495 
1496         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
1497                                      CXD2880_IO_TGT_DMD,
1498                                      0x10, nominal_rate_reg,
1499                                      sizeof(nominal_rate_reg));
1500         if (ret) {
1501                 slvt_unfreeze_reg(tnr_dmd);
1502                 return ret;
1503         }
1504 
1505         slvt_unfreeze_reg(tnr_dmd);
1506 
1507         diff_upper =
1508             (ctl_val_reg[0] & 0x7f) - (nominal_rate_reg[0] & 0x7f);
1509 
1510         if (diff_upper < -1 || diff_upper > 1)
1511                 return -EAGAIN;
1512 
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];
1517 
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];
1522 
1523         trl_ctl_val >>= 1;
1524         trcg_nominal_rate >>= 1;
1525 
1526         if (diff_upper == 1)
1527                 num =
1528                     (int)((trl_ctl_val + 0x80000000u) -
1529                           trcg_nominal_rate);
1530         else if (diff_upper == -1)
1531                 num =
1532                     -(int)((trcg_nominal_rate + 0x80000000u) -
1533                            trl_ctl_val);
1534         else
1535                 num = (int)(trl_ctl_val - trcg_nominal_rate);
1536 
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;
1542 
1543         den >>= 1;
1544 
1545         if (num >= 0)
1546                 *ppm = (num + (den / 2)) / den;
1547         else
1548                 *ppm = (num - (den / 2)) / den;
1549 
1550         return 0;
1551 }
1552 
1553 int cxd2880_tnrdmd_dvbt2_mon_sampling_offset_sub(struct
1554                                                  cxd2880_tnrdmd
1555                                                  *tnr_dmd,
1556                                                  int *ppm)
1557 {
1558         if (!tnr_dmd || !ppm)
1559                 return -EINVAL;
1560 
1561         if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN)
1562                 return -EINVAL;
1563 
1564         return cxd2880_tnrdmd_dvbt2_mon_sampling_offset(tnr_dmd->diver_sub,
1565                                                         ppm);
1566 }
1567 
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)
1571 {
1572         u8 data;
1573         u8 l1_post_ok = 0;
1574         int ret;
1575 
1576         if (!tnr_dmd || !qam)
1577                 return -EINVAL;
1578 
1579         if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
1580                 return -EINVAL;
1581 
1582         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
1583                 return -EINVAL;
1584 
1585         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2)
1586                 return -EINVAL;
1587 
1588         ret = slvt_freeze_reg(tnr_dmd);
1589         if (ret)
1590                 return ret;
1591 
1592         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
1593                                      CXD2880_IO_TGT_DMD,
1594                                      0x00, 0x0b);
1595         if (ret) {
1596                 slvt_unfreeze_reg(tnr_dmd);
1597                 return ret;
1598         }
1599 
1600         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
1601                                      CXD2880_IO_TGT_DMD,
1602                                      0x86, &l1_post_ok, 1);
1603         if (ret) {
1604                 slvt_unfreeze_reg(tnr_dmd);
1605                 return ret;
1606         }
1607 
1608         if (!(l1_post_ok & 0x01)) {
1609                 slvt_unfreeze_reg(tnr_dmd);
1610                 return -EAGAIN;
1611         }
1612 
1613         if (type == CXD2880_DVBT2_PLP_COMMON) {
1614                 ret = tnr_dmd->io->read_regs(tnr_dmd->io,
1615                                              CXD2880_IO_TGT_DMD,
1616                                              0xb6, &data, 1);
1617                 if (ret) {
1618                         slvt_unfreeze_reg(tnr_dmd);
1619                         return ret;
1620                 }
1621 
1622                 if (data == 0) {
1623                         slvt_unfreeze_reg(tnr_dmd);
1624                         return -EAGAIN;
1625                 }
1626 
1627                 ret = tnr_dmd->io->read_regs(tnr_dmd->io,
1628                                              CXD2880_IO_TGT_DMD,
1629                                              0xb1, &data, 1);
1630                 if (ret) {
1631                         slvt_unfreeze_reg(tnr_dmd);
1632                         return ret;
1633                 }
1634         } else {
1635                 ret = tnr_dmd->io->read_regs(tnr_dmd->io,
1636                                              CXD2880_IO_TGT_DMD,
1637                                              0x9e, &data, 1);
1638                 if (ret) {
1639                         slvt_unfreeze_reg(tnr_dmd);
1640                         return ret;
1641                 }
1642         }
1643 
1644         slvt_unfreeze_reg(tnr_dmd);
1645 
1646         *qam = (enum cxd2880_dvbt2_plp_constell)(data & 0x07);
1647 
1648         return ret;
1649 }
1650 
1651 int cxd2880_tnrdmd_dvbt2_mon_code_rate(struct cxd2880_tnrdmd
1652                                        *tnr_dmd,
1653                                        enum cxd2880_dvbt2_plp_btype
1654                                        type,
1655                                        enum
1656                                        cxd2880_dvbt2_plp_code_rate
1657                                        *code_rate)
1658 {
1659         u8 data;
1660         u8 l1_post_ok = 0;
1661         int ret;
1662 
1663         if (!tnr_dmd || !code_rate)
1664                 return -EINVAL;
1665 
1666         if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
1667                 return -EINVAL;
1668 
1669         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
1670                 return -EINVAL;
1671 
1672         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2)
1673                 return -EINVAL;
1674 
1675         ret = slvt_freeze_reg(tnr_dmd);
1676         if (ret)
1677                 return ret;
1678 
1679         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
1680                                      CXD2880_IO_TGT_DMD,
1681                                      0x00, 0x0b);
1682         if (ret) {
1683                 slvt_unfreeze_reg(tnr_dmd);
1684                 return ret;
1685         }
1686 
1687         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
1688                                      CXD2880_IO_TGT_DMD,
1689                                      0x86, &l1_post_ok, 1);
1690         if (ret) {
1691                 slvt_unfreeze_reg(tnr_dmd);
1692                 return ret;
1693         }
1694 
1695         if (!(l1_post_ok & 0x01)) {
1696                 slvt_unfreeze_reg(tnr_dmd);
1697                 return -EAGAIN;
1698         }
1699 
1700         if (type == CXD2880_DVBT2_PLP_COMMON) {
1701                 ret = tnr_dmd->io->read_regs(tnr_dmd->io,
1702                                              CXD2880_IO_TGT_DMD,
1703                                              0xb6, &data, 1);
1704                 if (ret) {
1705                         slvt_unfreeze_reg(tnr_dmd);
1706                         return ret;
1707                 }
1708 
1709                 if (data == 0) {
1710                         slvt_unfreeze_reg(tnr_dmd);
1711                         return -EAGAIN;
1712                 }
1713 
1714                 ret = tnr_dmd->io->read_regs(tnr_dmd->io,
1715                                              CXD2880_IO_TGT_DMD,
1716                                              0xb0, &data, 1);
1717                 if (ret) {
1718                         slvt_unfreeze_reg(tnr_dmd);
1719                         return ret;
1720                 }
1721         } else {
1722                 ret = tnr_dmd->io->read_regs(tnr_dmd->io,
1723                                              CXD2880_IO_TGT_DMD,
1724                                              0x9d, &data, 1);
1725                 if (ret) {
1726                         slvt_unfreeze_reg(tnr_dmd);
1727                         return ret;
1728                 }
1729         }
1730 
1731         slvt_unfreeze_reg(tnr_dmd);
1732 
1733         *code_rate = (enum cxd2880_dvbt2_plp_code_rate)(data & 0x07);
1734 
1735         return ret;
1736 }
1737 
1738 int cxd2880_tnrdmd_dvbt2_mon_profile(struct cxd2880_tnrdmd
1739                                      *tnr_dmd,
1740                                      enum cxd2880_dvbt2_profile
1741                                      *profile)
1742 {
1743         u8 data;
1744         int ret;
1745 
1746         if (!tnr_dmd || !profile)
1747                 return -EINVAL;
1748 
1749         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
1750                 return -EINVAL;
1751 
1752         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2)
1753                 return -EINVAL;
1754 
1755         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
1756                                      CXD2880_IO_TGT_DMD,
1757                                      0x00, 0x0b);
1758         if (ret)
1759                 return ret;
1760 
1761         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
1762                                      CXD2880_IO_TGT_DMD,
1763                                      0x22, &data, sizeof(data));
1764         if (ret)
1765                 return ret;
1766 
1767         if (data & 0x02) {
1768                 if (data & 0x01)
1769                         *profile = CXD2880_DVBT2_PROFILE_LITE;
1770                 else
1771                         *profile = CXD2880_DVBT2_PROFILE_BASE;
1772         } else {
1773                 ret = -EAGAIN;
1774                 if (tnr_dmd->diver_mode ==
1775                     CXD2880_TNRDMD_DIVERMODE_MAIN)
1776                         ret =
1777                             cxd2880_tnrdmd_dvbt2_mon_profile(tnr_dmd->diver_sub,
1778                                                              profile);
1779 
1780                 return ret;
1781         }
1782 
1783         return 0;
1784 }
1785 
1786 static int dvbt2_calc_ssi(struct cxd2880_tnrdmd *tnr_dmd,
1787                           int rf_lvl, u8 *ssi)
1788 {
1789         enum cxd2880_dvbt2_plp_constell qam;
1790         enum cxd2880_dvbt2_plp_code_rate code_rate;
1791         int prel;
1792         int temp_ssi = 0;
1793         int ret;
1794 
1795         if (!tnr_dmd || !ssi)
1796                 return -EINVAL;
1797 
1798         ret =
1799             cxd2880_tnrdmd_dvbt2_mon_qam(tnr_dmd, CXD2880_DVBT2_PLP_DATA, &qam);
1800         if (ret)
1801                 return ret;
1802 
1803         ret =
1804             cxd2880_tnrdmd_dvbt2_mon_code_rate(tnr_dmd, CXD2880_DVBT2_PLP_DATA,
1805                                                &code_rate);
1806         if (ret)
1807                 return ret;
1808 
1809         if (code_rate > CXD2880_DVBT2_R2_5 || qam > CXD2880_DVBT2_QAM256)
1810                 return -EINVAL;
1811 
1812         prel = rf_lvl - ref_dbm_1000[qam][code_rate];
1813 
1814         if (prel < -15000)
1815                 temp_ssi = 0;
1816         else if (prel < 0)
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;
1822         else
1823                 temp_ssi = 100;
1824 
1825         *ssi = (temp_ssi > 100) ? 100 : (u8)temp_ssi;
1826 
1827         return ret;
1828 }
1829 
1830 int cxd2880_tnrdmd_dvbt2_mon_ssi(struct cxd2880_tnrdmd *tnr_dmd,
1831                                  u8 *ssi)
1832 {
1833         int rf_lvl = 0;
1834         int ret;
1835 
1836         if (!tnr_dmd || !ssi)
1837                 return -EINVAL;
1838 
1839         if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
1840                 return -EINVAL;
1841 
1842         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
1843                 return -EINVAL;
1844 
1845         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2)
1846                 return -EINVAL;
1847 
1848         ret = cxd2880_tnrdmd_mon_rf_lvl(tnr_dmd, &rf_lvl);
1849         if (ret)
1850                 return ret;
1851 
1852         return dvbt2_calc_ssi(tnr_dmd, rf_lvl, ssi);
1853 }
1854 
1855 int cxd2880_tnrdmd_dvbt2_mon_ssi_sub(struct cxd2880_tnrdmd
1856                                      *tnr_dmd, u8 *ssi)
1857 {
1858         int rf_lvl = 0;
1859         int ret;
1860 
1861         if (!tnr_dmd || !ssi)
1862                 return -EINVAL;
1863 
1864         if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN)
1865                 return -EINVAL;
1866 
1867         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
1868                 return -EINVAL;
1869 
1870         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT2)
1871                 return -EINVAL;
1872 
1873         ret = cxd2880_tnrdmd_mon_rf_lvl(tnr_dmd->diver_sub, &rf_lvl);
1874         if (ret)
1875                 return ret;
1876 
1877         return dvbt2_calc_ssi(tnr_dmd, rf_lvl, ssi);
1878 }

/* [<][>][^][v][top][bottom][index][help] */