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

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

DEFINITIONS

This source file includes following definitions.
  1. cxd2880_tnrdmd_dvbt_mon_sync_stat
  2. cxd2880_tnrdmd_dvbt_mon_sync_stat_sub
  3. cxd2880_tnrdmd_dvbt_mon_mode_guard
  4. cxd2880_tnrdmd_dvbt_mon_carrier_offset
  5. cxd2880_tnrdmd_dvbt_mon_carrier_offset_sub
  6. cxd2880_tnrdmd_dvbt_mon_tps_info
  7. cxd2880_tnrdmd_dvbt_mon_packet_error_number
  8. cxd2880_tnrdmd_dvbt_mon_spectrum_sense
  9. dvbt_read_snr_reg
  10. dvbt_calc_snr
  11. cxd2880_tnrdmd_dvbt_mon_snr
  12. cxd2880_tnrdmd_dvbt_mon_snr_diver
  13. cxd2880_tnrdmd_dvbt_mon_sampling_offset
  14. cxd2880_tnrdmd_dvbt_mon_sampling_offset_sub
  15. dvbt_calc_ssi
  16. cxd2880_tnrdmd_dvbt_mon_ssi
  17. cxd2880_tnrdmd_dvbt_mon_ssi_sub
  18. is_tps_locked

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * cxd2880_tnrdmd_dvbt_mon.c
   4  * Sony CXD2880 DVB-T2/T tuner + demodulator driver
   5  * DVB-T 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_dvbt.h"
  12 #include "cxd2880_tnrdmd_dvbt_mon.h"
  13 
  14 #include <media/dvb_math.h>
  15 
  16 static const int ref_dbm_1000[3][5] = {
  17         {-93000, -91000, -90000, -89000, -88000},
  18         {-87000, -85000, -84000, -83000, -82000},
  19         {-82000, -80000, -78000, -77000, -76000},
  20 };
  21 
  22 static int is_tps_locked(struct cxd2880_tnrdmd *tnr_dmd);
  23 
  24 int cxd2880_tnrdmd_dvbt_mon_sync_stat(struct cxd2880_tnrdmd
  25                                       *tnr_dmd, u8 *sync_stat,
  26                                       u8 *ts_lock_stat,
  27                                       u8 *unlock_detected)
  28 {
  29         u8 rdata = 0x00;
  30         int ret;
  31 
  32         if (!tnr_dmd || !sync_stat || !ts_lock_stat || !unlock_detected)
  33                 return -EINVAL;
  34 
  35         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
  36                 return -EINVAL;
  37         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
  38                 return -EINVAL;
  39 
  40         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  41                                      CXD2880_IO_TGT_DMD,
  42                                      0x00, 0x0d);
  43         if (ret)
  44                 return ret;
  45 
  46         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
  47                                      CXD2880_IO_TGT_DMD,
  48                                      0x10, &rdata, 1);
  49         if (ret)
  50                 return ret;
  51 
  52         *unlock_detected = (rdata & 0x10) ? 1 : 0;
  53         *sync_stat = rdata & 0x07;
  54         *ts_lock_stat = (rdata & 0x20) ? 1 : 0;
  55 
  56         if (*sync_stat == 0x07)
  57                 return -EAGAIN;
  58 
  59         return ret;
  60 }
  61 
  62 int cxd2880_tnrdmd_dvbt_mon_sync_stat_sub(struct cxd2880_tnrdmd
  63                                           *tnr_dmd, u8 *sync_stat,
  64                                           u8 *unlock_detected)
  65 {
  66         u8 ts_lock_stat = 0;
  67 
  68         if (!tnr_dmd || !sync_stat || !unlock_detected)
  69                 return -EINVAL;
  70 
  71         if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN)
  72                 return -EINVAL;
  73 
  74         return cxd2880_tnrdmd_dvbt_mon_sync_stat(tnr_dmd->diver_sub,
  75                                                  sync_stat,
  76                                                  &ts_lock_stat,
  77                                                  unlock_detected);
  78 }
  79 
  80 int cxd2880_tnrdmd_dvbt_mon_mode_guard(struct cxd2880_tnrdmd
  81                                        *tnr_dmd,
  82                                        enum cxd2880_dvbt_mode
  83                                        *mode,
  84                                        enum cxd2880_dvbt_guard
  85                                        *guard)
  86 {
  87         u8 rdata = 0x00;
  88         int ret;
  89 
  90         if (!tnr_dmd || !mode || !guard)
  91                 return -EINVAL;
  92 
  93         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
  94                 return -EINVAL;
  95 
  96         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
  97                 return -EINVAL;
  98 
  99         ret = slvt_freeze_reg(tnr_dmd);
 100         if (ret)
 101                 return ret;
 102 
 103         ret = is_tps_locked(tnr_dmd);
 104         if (ret) {
 105                 slvt_unfreeze_reg(tnr_dmd);
 106 
 107                 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN)
 108                         ret =
 109                             cxd2880_tnrdmd_dvbt_mon_mode_guard(tnr_dmd->diver_sub,
 110                                                                mode, guard);
 111 
 112                 return ret;
 113         }
 114 
 115         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
 116                                      CXD2880_IO_TGT_DMD,
 117                                      0x00, 0x0d);
 118         if (ret) {
 119                 slvt_unfreeze_reg(tnr_dmd);
 120                 return ret;
 121         }
 122 
 123         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
 124                                      CXD2880_IO_TGT_DMD,
 125                                      0x1b, &rdata, 1);
 126         if (ret) {
 127                 slvt_unfreeze_reg(tnr_dmd);
 128                 return ret;
 129         }
 130 
 131         slvt_unfreeze_reg(tnr_dmd);
 132 
 133         *mode = (enum cxd2880_dvbt_mode)((rdata >> 2) & 0x03);
 134         *guard = (enum cxd2880_dvbt_guard)(rdata & 0x03);
 135 
 136         return ret;
 137 }
 138 
 139 int cxd2880_tnrdmd_dvbt_mon_carrier_offset(struct cxd2880_tnrdmd
 140                                            *tnr_dmd, int *offset)
 141 {
 142         u8 rdata[4];
 143         u32 ctl_val = 0;
 144         int ret;
 145 
 146         if (!tnr_dmd || !offset)
 147                 return -EINVAL;
 148 
 149         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
 150                 return -EINVAL;
 151 
 152         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
 153                 return -EINVAL;
 154 
 155         ret = slvt_freeze_reg(tnr_dmd);
 156         if (ret)
 157                 return ret;
 158 
 159         ret = is_tps_locked(tnr_dmd);
 160         if (ret) {
 161                 slvt_unfreeze_reg(tnr_dmd);
 162                 return ret;
 163         }
 164 
 165         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
 166                                      CXD2880_IO_TGT_DMD,
 167                                      0x00, 0x0d);
 168         if (ret) {
 169                 slvt_unfreeze_reg(tnr_dmd);
 170                 return ret;
 171         }
 172 
 173         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
 174                                      CXD2880_IO_TGT_DMD,
 175                                      0x1d, rdata, 4);
 176         if (ret) {
 177                 slvt_unfreeze_reg(tnr_dmd);
 178                 return ret;
 179         }
 180 
 181         slvt_unfreeze_reg(tnr_dmd);
 182 
 183         ctl_val =
 184             ((rdata[0] & 0x1f) << 24) | (rdata[1] << 16) | (rdata[2] << 8) |
 185             (rdata[3]);
 186         *offset = cxd2880_convert2s_complement(ctl_val, 29);
 187         *offset = -1 * ((*offset) * tnr_dmd->bandwidth / 235);
 188 
 189         return ret;
 190 }
 191 
 192 int cxd2880_tnrdmd_dvbt_mon_carrier_offset_sub(struct
 193                                                cxd2880_tnrdmd
 194                                                *tnr_dmd,
 195                                                int *offset)
 196 {
 197         if (!tnr_dmd || !offset)
 198                 return -EINVAL;
 199 
 200         if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN)
 201                 return -EINVAL;
 202 
 203         return cxd2880_tnrdmd_dvbt_mon_carrier_offset(tnr_dmd->diver_sub,
 204                                                       offset);
 205 }
 206 
 207 int cxd2880_tnrdmd_dvbt_mon_tps_info(struct cxd2880_tnrdmd
 208                                      *tnr_dmd,
 209                                      struct cxd2880_dvbt_tpsinfo
 210                                      *info)
 211 {
 212         u8 rdata[7];
 213         u8 cell_id_ok = 0;
 214         int ret;
 215 
 216         if (!tnr_dmd || !info)
 217                 return -EINVAL;
 218 
 219         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
 220                 return -EINVAL;
 221 
 222         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
 223                 return -EINVAL;
 224 
 225         ret = slvt_freeze_reg(tnr_dmd);
 226         if (ret)
 227                 return ret;
 228 
 229         ret = is_tps_locked(tnr_dmd);
 230         if (ret) {
 231                 slvt_unfreeze_reg(tnr_dmd);
 232 
 233                 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN)
 234                         ret =
 235                             cxd2880_tnrdmd_dvbt_mon_tps_info(tnr_dmd->diver_sub,
 236                                                              info);
 237 
 238                 return ret;
 239         }
 240 
 241         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
 242                                      CXD2880_IO_TGT_DMD,
 243                                      0x00, 0x0d);
 244         if (ret) {
 245                 slvt_unfreeze_reg(tnr_dmd);
 246                 return ret;
 247         }
 248 
 249         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
 250                                      CXD2880_IO_TGT_DMD,
 251                                      0x29, rdata, 7);
 252         if (ret) {
 253                 slvt_unfreeze_reg(tnr_dmd);
 254                 return ret;
 255         }
 256 
 257         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
 258                                      CXD2880_IO_TGT_DMD,
 259                                      0x00, 0x11);
 260         if (ret) {
 261                 slvt_unfreeze_reg(tnr_dmd);
 262                 return ret;
 263         }
 264 
 265         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
 266                                      CXD2880_IO_TGT_DMD,
 267                                      0xd5, &cell_id_ok, 1);
 268         if (ret) {
 269                 slvt_unfreeze_reg(tnr_dmd);
 270                 return ret;
 271         }
 272 
 273         slvt_unfreeze_reg(tnr_dmd);
 274 
 275         info->constellation =
 276             (enum cxd2880_dvbt_constellation)((rdata[0] >> 6) & 0x03);
 277         info->hierarchy = (enum cxd2880_dvbt_hierarchy)((rdata[0] >> 3) & 0x07);
 278         info->rate_hp = (enum cxd2880_dvbt_coderate)(rdata[0] & 0x07);
 279         info->rate_lp = (enum cxd2880_dvbt_coderate)((rdata[1] >> 5) & 0x07);
 280         info->guard = (enum cxd2880_dvbt_guard)((rdata[1] >> 3) & 0x03);
 281         info->mode = (enum cxd2880_dvbt_mode)((rdata[1] >> 1) & 0x03);
 282         info->fnum = (rdata[2] >> 6) & 0x03;
 283         info->length_indicator = rdata[2] & 0x3f;
 284         info->cell_id = (rdata[3] << 8) | rdata[4];
 285         info->reserved_even = rdata[5] & 0x3f;
 286         info->reserved_odd = rdata[6] & 0x3f;
 287 
 288         info->cell_id_ok = cell_id_ok & 0x01;
 289 
 290         return ret;
 291 }
 292 
 293 int cxd2880_tnrdmd_dvbt_mon_packet_error_number(struct
 294                                                 cxd2880_tnrdmd
 295                                                 *tnr_dmd,
 296                                                 u32 *pen)
 297 {
 298         u8 rdata[3];
 299         int ret;
 300 
 301         if (!tnr_dmd || !pen)
 302                 return -EINVAL;
 303 
 304         if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
 305                 return -EINVAL;
 306 
 307         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
 308                 return -EINVAL;
 309 
 310         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
 311                 return -EINVAL;
 312 
 313         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
 314                                      CXD2880_IO_TGT_DMD,
 315                                      0x00, 0x0d);
 316         if (ret)
 317                 return ret;
 318 
 319         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
 320                                      CXD2880_IO_TGT_DMD,
 321                                      0x26, rdata, 3);
 322         if (ret)
 323                 return ret;
 324 
 325         if (!(rdata[0] & 0x01))
 326                 return -EAGAIN;
 327 
 328         *pen = (rdata[1] << 8) | rdata[2];
 329 
 330         return ret;
 331 }
 332 
 333 int cxd2880_tnrdmd_dvbt_mon_spectrum_sense(struct cxd2880_tnrdmd
 334                                            *tnr_dmd,
 335                                             enum
 336                                             cxd2880_tnrdmd_spectrum_sense
 337                                             *sense)
 338 {
 339         u8 data = 0;
 340         int ret;
 341 
 342         if (!tnr_dmd || !sense)
 343                 return -EINVAL;
 344 
 345         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
 346                 return -EINVAL;
 347 
 348         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
 349                 return -EINVAL;
 350 
 351         ret = slvt_freeze_reg(tnr_dmd);
 352         if (ret)
 353                 return ret;
 354 
 355         ret = is_tps_locked(tnr_dmd);
 356         if (ret) {
 357                 slvt_unfreeze_reg(tnr_dmd);
 358 
 359                 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN)
 360                         ret = cxd2880_tnrdmd_dvbt_mon_spectrum_sense(tnr_dmd->diver_sub,
 361                                                                      sense);
 362 
 363                 return ret;
 364         }
 365 
 366         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
 367                                      CXD2880_IO_TGT_DMD,
 368                                      0x00, 0x0d);
 369         if (ret) {
 370                 slvt_unfreeze_reg(tnr_dmd);
 371                 return ret;
 372         }
 373 
 374         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
 375                                      CXD2880_IO_TGT_DMD,
 376                                      0x1c, &data, sizeof(data));
 377         if (ret) {
 378                 slvt_unfreeze_reg(tnr_dmd);
 379                 return ret;
 380         }
 381 
 382         slvt_unfreeze_reg(tnr_dmd);
 383 
 384         *sense =
 385             (data & 0x01) ? CXD2880_TNRDMD_SPECTRUM_INV :
 386             CXD2880_TNRDMD_SPECTRUM_NORMAL;
 387 
 388         return ret;
 389 }
 390 
 391 static int dvbt_read_snr_reg(struct cxd2880_tnrdmd *tnr_dmd,
 392                              u16 *reg_value)
 393 {
 394         u8 rdata[2];
 395         int ret;
 396 
 397         if (!tnr_dmd || !reg_value)
 398                 return -EINVAL;
 399 
 400         ret = slvt_freeze_reg(tnr_dmd);
 401         if (ret)
 402                 return ret;
 403 
 404         ret = is_tps_locked(tnr_dmd);
 405         if (ret) {
 406                 slvt_unfreeze_reg(tnr_dmd);
 407                 return ret;
 408         }
 409 
 410         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
 411                                      CXD2880_IO_TGT_DMD,
 412                                      0x00, 0x0d);
 413         if (ret) {
 414                 slvt_unfreeze_reg(tnr_dmd);
 415                 return ret;
 416         }
 417 
 418         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
 419                                      CXD2880_IO_TGT_DMD,
 420                                      0x13, rdata, 2);
 421         if (ret) {
 422                 slvt_unfreeze_reg(tnr_dmd);
 423                 return ret;
 424         }
 425 
 426         slvt_unfreeze_reg(tnr_dmd);
 427 
 428         *reg_value = (rdata[0] << 8) | rdata[1];
 429 
 430         return ret;
 431 }
 432 
 433 static int dvbt_calc_snr(struct cxd2880_tnrdmd *tnr_dmd,
 434                          u32 reg_value, int *snr)
 435 {
 436         if (!tnr_dmd || !snr)
 437                 return -EINVAL;
 438 
 439         if (reg_value == 0)
 440                 return -EAGAIN;
 441 
 442         if (reg_value > 4996)
 443                 reg_value = 4996;
 444 
 445         *snr = intlog10(reg_value) - intlog10(5350 - reg_value);
 446         *snr = (*snr + 839) / 1678 + 28500;
 447 
 448         return 0;
 449 }
 450 
 451 int cxd2880_tnrdmd_dvbt_mon_snr(struct cxd2880_tnrdmd *tnr_dmd,
 452                                 int *snr)
 453 {
 454         u16 reg_value = 0;
 455         int ret;
 456 
 457         if (!tnr_dmd || !snr)
 458                 return -EINVAL;
 459 
 460         *snr = -1000 * 1000;
 461 
 462         if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
 463                 return -EINVAL;
 464 
 465         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
 466                 return -EINVAL;
 467 
 468         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
 469                 return -EINVAL;
 470 
 471         if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) {
 472                 ret = dvbt_read_snr_reg(tnr_dmd, &reg_value);
 473                 if (ret)
 474                         return ret;
 475 
 476                 ret = dvbt_calc_snr(tnr_dmd, reg_value, snr);
 477         } else {
 478                 int snr_main = 0;
 479                 int snr_sub = 0;
 480 
 481                 ret =
 482                     cxd2880_tnrdmd_dvbt_mon_snr_diver(tnr_dmd, snr, &snr_main,
 483                                                       &snr_sub);
 484         }
 485 
 486         return ret;
 487 }
 488 
 489 int cxd2880_tnrdmd_dvbt_mon_snr_diver(struct cxd2880_tnrdmd
 490                                       *tnr_dmd, int *snr,
 491                                       int *snr_main, int *snr_sub)
 492 {
 493         u16 reg_value = 0;
 494         u32 reg_value_sum = 0;
 495         int ret;
 496 
 497         if (!tnr_dmd || !snr || !snr_main || !snr_sub)
 498                 return -EINVAL;
 499 
 500         *snr = -1000 * 1000;
 501         *snr_main = -1000 * 1000;
 502         *snr_sub = -1000 * 1000;
 503 
 504         if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN)
 505                 return -EINVAL;
 506 
 507         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
 508                 return -EINVAL;
 509 
 510         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
 511                 return -EINVAL;
 512 
 513         ret = dvbt_read_snr_reg(tnr_dmd, &reg_value);
 514         if (!ret) {
 515                 ret = dvbt_calc_snr(tnr_dmd, reg_value, snr_main);
 516                 if (ret)
 517                         reg_value = 0;
 518         } else if (ret == -EAGAIN) {
 519                 reg_value = 0;
 520         } else {
 521                 return ret;
 522         }
 523 
 524         reg_value_sum += reg_value;
 525 
 526         ret = dvbt_read_snr_reg(tnr_dmd->diver_sub, &reg_value);
 527         if (!ret) {
 528                 ret = dvbt_calc_snr(tnr_dmd->diver_sub, reg_value, snr_sub);
 529                 if (ret)
 530                         reg_value = 0;
 531         } else if (ret == -EAGAIN) {
 532                 reg_value = 0;
 533         } else {
 534                 return ret;
 535         }
 536 
 537         reg_value_sum += reg_value;
 538 
 539         return dvbt_calc_snr(tnr_dmd, reg_value_sum, snr);
 540 }
 541 
 542 int cxd2880_tnrdmd_dvbt_mon_sampling_offset(struct cxd2880_tnrdmd
 543                                             *tnr_dmd, int *ppm)
 544 {
 545         u8 ctl_val_reg[5];
 546         u8 nominal_rate_reg[5];
 547         u32 trl_ctl_val = 0;
 548         u32 trcg_nominal_rate = 0;
 549         int num;
 550         int den;
 551         s8 diff_upper = 0;
 552         int ret;
 553 
 554         if (!tnr_dmd || !ppm)
 555                 return -EINVAL;
 556 
 557         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
 558                 return -EINVAL;
 559 
 560         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
 561                 return -EINVAL;
 562 
 563         ret = slvt_freeze_reg(tnr_dmd);
 564         if (ret)
 565                 return ret;
 566 
 567         ret = is_tps_locked(tnr_dmd);
 568         if (ret) {
 569                 slvt_unfreeze_reg(tnr_dmd);
 570                 return ret;
 571         }
 572 
 573         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
 574                                      CXD2880_IO_TGT_DMD,
 575                                      0x00, 0x0d);
 576         if (ret) {
 577                 slvt_unfreeze_reg(tnr_dmd);
 578                 return ret;
 579         }
 580 
 581         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
 582                                      CXD2880_IO_TGT_DMD,
 583                                      0x21, ctl_val_reg,
 584                                      sizeof(ctl_val_reg));
 585         if (ret) {
 586                 slvt_unfreeze_reg(tnr_dmd);
 587                 return ret;
 588         }
 589 
 590         ret = tnr_dmd->io->write_reg(tnr_dmd->io,
 591                                      CXD2880_IO_TGT_DMD,
 592                                      0x00, 0x04);
 593         if (ret) {
 594                 slvt_unfreeze_reg(tnr_dmd);
 595                 return ret;
 596         }
 597 
 598         ret = tnr_dmd->io->read_regs(tnr_dmd->io,
 599                                      CXD2880_IO_TGT_DMD,
 600                                      0x60, nominal_rate_reg,
 601                                      sizeof(nominal_rate_reg));
 602         if (ret) {
 603                 slvt_unfreeze_reg(tnr_dmd);
 604                 return ret;
 605         }
 606 
 607         slvt_unfreeze_reg(tnr_dmd);
 608 
 609         diff_upper =
 610             (ctl_val_reg[0] & 0x7f) - (nominal_rate_reg[0] & 0x7f);
 611 
 612         if (diff_upper < -1 || diff_upper > 1)
 613                 return -EAGAIN;
 614 
 615         trl_ctl_val = ctl_val_reg[1] << 24;
 616         trl_ctl_val |= ctl_val_reg[2] << 16;
 617         trl_ctl_val |= ctl_val_reg[3] << 8;
 618         trl_ctl_val |= ctl_val_reg[4];
 619 
 620         trcg_nominal_rate = nominal_rate_reg[1] << 24;
 621         trcg_nominal_rate |= nominal_rate_reg[2] << 16;
 622         trcg_nominal_rate |= nominal_rate_reg[3] << 8;
 623         trcg_nominal_rate |= nominal_rate_reg[4];
 624 
 625         trl_ctl_val >>= 1;
 626         trcg_nominal_rate >>= 1;
 627 
 628         if (diff_upper == 1)
 629                 num =
 630                     (int)((trl_ctl_val + 0x80000000u) -
 631                           trcg_nominal_rate);
 632         else if (diff_upper == -1)
 633                 num =
 634                     -(int)((trcg_nominal_rate + 0x80000000u) -
 635                            trl_ctl_val);
 636         else
 637                 num = (int)(trl_ctl_val - trcg_nominal_rate);
 638 
 639         den = (nominal_rate_reg[0] & 0x7f) << 24;
 640         den |= nominal_rate_reg[1] << 16;
 641         den |= nominal_rate_reg[2] << 8;
 642         den |= nominal_rate_reg[3];
 643         den = (den + (390625 / 2)) / 390625;
 644 
 645         den >>= 1;
 646 
 647         if (num >= 0)
 648                 *ppm = (num + (den / 2)) / den;
 649         else
 650                 *ppm = (num - (den / 2)) / den;
 651 
 652         return ret;
 653 }
 654 
 655 int cxd2880_tnrdmd_dvbt_mon_sampling_offset_sub(struct
 656                                                 cxd2880_tnrdmd
 657                                                 *tnr_dmd, int *ppm)
 658 {
 659         if (!tnr_dmd || !ppm)
 660                 return -EINVAL;
 661 
 662         if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN)
 663                 return -EINVAL;
 664 
 665         return cxd2880_tnrdmd_dvbt_mon_sampling_offset(tnr_dmd->diver_sub, ppm);
 666 }
 667 
 668 static int dvbt_calc_ssi(struct cxd2880_tnrdmd *tnr_dmd,
 669                          int rf_lvl, u8 *ssi)
 670 {
 671         struct cxd2880_dvbt_tpsinfo tps;
 672         int prel;
 673         int temp_ssi = 0;
 674         int ret;
 675 
 676         if (!tnr_dmd || !ssi)
 677                 return -EINVAL;
 678 
 679         ret = cxd2880_tnrdmd_dvbt_mon_tps_info(tnr_dmd, &tps);
 680         if (ret)
 681                 return ret;
 682 
 683         if (tps.constellation >= CXD2880_DVBT_CONSTELLATION_RESERVED_3 ||
 684             tps.rate_hp >= CXD2880_DVBT_CODERATE_RESERVED_5)
 685                 return -EINVAL;
 686 
 687         prel = rf_lvl - ref_dbm_1000[tps.constellation][tps.rate_hp];
 688 
 689         if (prel < -15000)
 690                 temp_ssi = 0;
 691         else if (prel < 0)
 692                 temp_ssi = ((2 * (prel + 15000)) + 1500) / 3000;
 693         else if (prel < 20000)
 694                 temp_ssi = (((4 * prel) + 500) / 1000) + 10;
 695         else if (prel < 35000)
 696                 temp_ssi = (((2 * (prel - 20000)) + 1500) / 3000) + 90;
 697         else
 698                 temp_ssi = 100;
 699 
 700         *ssi = (temp_ssi > 100) ? 100 : (u8)temp_ssi;
 701 
 702         return ret;
 703 }
 704 
 705 int cxd2880_tnrdmd_dvbt_mon_ssi(struct cxd2880_tnrdmd *tnr_dmd,
 706                                 u8 *ssi)
 707 {
 708         int rf_lvl = 0;
 709         int ret;
 710 
 711         if (!tnr_dmd || !ssi)
 712                 return -EINVAL;
 713 
 714         if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
 715                 return -EINVAL;
 716 
 717         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
 718                 return -EINVAL;
 719 
 720         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
 721                 return -EINVAL;
 722 
 723         ret = cxd2880_tnrdmd_mon_rf_lvl(tnr_dmd, &rf_lvl);
 724         if (ret)
 725                 return ret;
 726 
 727         return dvbt_calc_ssi(tnr_dmd, rf_lvl, ssi);
 728 }
 729 
 730 int cxd2880_tnrdmd_dvbt_mon_ssi_sub(struct cxd2880_tnrdmd *tnr_dmd,
 731                                     u8 *ssi)
 732 {
 733         int rf_lvl = 0;
 734         int ret;
 735 
 736         if (!tnr_dmd || !ssi)
 737                 return -EINVAL;
 738 
 739         if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN)
 740                 return -EINVAL;
 741 
 742         if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
 743                 return -EINVAL;
 744 
 745         if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
 746                 return -EINVAL;
 747 
 748         ret = cxd2880_tnrdmd_mon_rf_lvl(tnr_dmd->diver_sub, &rf_lvl);
 749         if (ret)
 750                 return ret;
 751 
 752         return dvbt_calc_ssi(tnr_dmd, rf_lvl, ssi);
 753 }
 754 
 755 static int is_tps_locked(struct cxd2880_tnrdmd *tnr_dmd)
 756 {
 757         u8 sync = 0;
 758         u8 tslock = 0;
 759         u8 early_unlock = 0;
 760         int ret;
 761 
 762         if (!tnr_dmd)
 763                 return -EINVAL;
 764 
 765         ret =
 766             cxd2880_tnrdmd_dvbt_mon_sync_stat(tnr_dmd, &sync, &tslock,
 767                                               &early_unlock);
 768         if (ret)
 769                 return ret;
 770 
 771         if (sync != 6)
 772                 return -EAGAIN;
 773 
 774         return 0;
 775 }

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