linux/drivers/media/dvb-frontends/cxd2880/cxd2880_top.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * cxd2880_top.c
   4 * Sony CXD2880 DVB-T2/T tuner + demodulator driver
   5 *
   6 * Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
   7 */
   8
   9#define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
  10
  11#include <linux/spi/spi.h>
  12
  13#include <media/dvb_frontend.h>
  14#include <media/dvb_math.h>
  15
  16#include "cxd2880.h"
  17#include "cxd2880_tnrdmd_mon.h"
  18#include "cxd2880_tnrdmd_dvbt2_mon.h"
  19#include "cxd2880_tnrdmd_dvbt_mon.h"
  20#include "cxd2880_integ.h"
  21#include "cxd2880_tnrdmd_dvbt2.h"
  22#include "cxd2880_tnrdmd_dvbt.h"
  23#include "cxd2880_devio_spi.h"
  24#include "cxd2880_spi_device.h"
  25#include "cxd2880_tnrdmd_driver_version.h"
  26
  27struct cxd2880_priv {
  28        struct cxd2880_tnrdmd tnrdmd;
  29        struct spi_device *spi;
  30        struct cxd2880_io regio;
  31        struct cxd2880_spi_device spi_device;
  32        struct cxd2880_spi cxd2880_spi;
  33        struct cxd2880_dvbt_tune_param dvbt_tune_param;
  34        struct cxd2880_dvbt2_tune_param dvbt2_tune_param;
  35        struct mutex *spi_mutex; /* For SPI access exclusive control */
  36        unsigned long pre_ber_update;
  37        unsigned long pre_ber_interval;
  38        unsigned long post_ber_update;
  39        unsigned long post_ber_interval;
  40        unsigned long ucblock_update;
  41        unsigned long ucblock_interval;
  42        enum fe_status s;
  43};
  44
  45static int cxd2880_pre_bit_err_t(struct cxd2880_tnrdmd *tnrdmd,
  46                                 u32 *pre_bit_err, u32 *pre_bit_count)
  47{
  48        u8 rdata[2];
  49        int ret;
  50
  51        if (!tnrdmd || !pre_bit_err || !pre_bit_count)
  52                return -EINVAL;
  53
  54        if (tnrdmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
  55                return -EINVAL;
  56
  57        if (tnrdmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
  58                return -EINVAL;
  59
  60        if (tnrdmd->sys != CXD2880_DTV_SYS_DVBT)
  61                return -EINVAL;
  62
  63        ret = slvt_freeze_reg(tnrdmd);
  64        if (ret)
  65                return ret;
  66
  67        ret = tnrdmd->io->write_reg(tnrdmd->io,
  68                                    CXD2880_IO_TGT_DMD,
  69                                    0x00, 0x10);
  70        if (ret) {
  71                slvt_unfreeze_reg(tnrdmd);
  72                return ret;
  73        }
  74
  75        ret = tnrdmd->io->read_regs(tnrdmd->io,
  76                                    CXD2880_IO_TGT_DMD,
  77                                    0x39, rdata, 1);
  78        if (ret) {
  79                slvt_unfreeze_reg(tnrdmd);
  80                return ret;
  81        }
  82
  83        if ((rdata[0] & 0x01) == 0) {
  84                slvt_unfreeze_reg(tnrdmd);
  85                return -EAGAIN;
  86        }
  87
  88        ret = tnrdmd->io->read_regs(tnrdmd->io,
  89                                    CXD2880_IO_TGT_DMD,
  90                                    0x22, rdata, 2);
  91        if (ret) {
  92                slvt_unfreeze_reg(tnrdmd);
  93                return ret;
  94        }
  95
  96        *pre_bit_err = (rdata[0] << 8) | rdata[1];
  97
  98        ret = tnrdmd->io->read_regs(tnrdmd->io,
  99                                    CXD2880_IO_TGT_DMD,
 100                                    0x6f, rdata, 1);
 101        if (ret) {
 102                slvt_unfreeze_reg(tnrdmd);
 103                return ret;
 104        }
 105
 106        slvt_unfreeze_reg(tnrdmd);
 107
 108        *pre_bit_count = ((rdata[0] & 0x07) == 0) ?
 109                         256 : (0x1000 << (rdata[0] & 0x07));
 110
 111        return 0;
 112}
 113
 114static int cxd2880_pre_bit_err_t2(struct cxd2880_tnrdmd *tnrdmd,
 115                                  u32 *pre_bit_err,
 116                                  u32 *pre_bit_count)
 117{
 118        u32 period_exp = 0;
 119        u32 n_ldpc = 0;
 120        u8 data[5];
 121        int ret;
 122
 123        if (!tnrdmd || !pre_bit_err || !pre_bit_count)
 124                return -EINVAL;
 125
 126        if (tnrdmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
 127                return -EINVAL;
 128
 129        if (tnrdmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
 130                return -EINVAL;
 131
 132        if (tnrdmd->sys != CXD2880_DTV_SYS_DVBT2)
 133                return -EINVAL;
 134
 135        ret = slvt_freeze_reg(tnrdmd);
 136        if (ret)
 137                return ret;
 138
 139        ret = tnrdmd->io->write_reg(tnrdmd->io,
 140                                    CXD2880_IO_TGT_DMD,
 141                                    0x00, 0x0b);
 142        if (ret) {
 143                slvt_unfreeze_reg(tnrdmd);
 144                return ret;
 145        }
 146
 147        ret = tnrdmd->io->read_regs(tnrdmd->io,
 148                                    CXD2880_IO_TGT_DMD,
 149                                    0x3c, data, sizeof(data));
 150        if (ret) {
 151                slvt_unfreeze_reg(tnrdmd);
 152                return ret;
 153        }
 154
 155        if (!(data[0] & 0x01)) {
 156                slvt_unfreeze_reg(tnrdmd);
 157                return -EAGAIN;
 158        }
 159        *pre_bit_err =
 160        ((data[1] & 0x0f) << 24) | (data[2] << 16) | (data[3] << 8) | data[4];
 161
 162        ret = tnrdmd->io->read_regs(tnrdmd->io,
 163                                    CXD2880_IO_TGT_DMD,
 164                                    0xa0, data, 1);
 165        if (ret) {
 166                slvt_unfreeze_reg(tnrdmd);
 167                return ret;
 168        }
 169
 170        if (((enum cxd2880_dvbt2_plp_fec)(data[0] & 0x03)) ==
 171            CXD2880_DVBT2_FEC_LDPC_16K)
 172                n_ldpc = 16200;
 173        else
 174                n_ldpc = 64800;
 175        slvt_unfreeze_reg(tnrdmd);
 176
 177        ret = tnrdmd->io->write_reg(tnrdmd->io,
 178                                    CXD2880_IO_TGT_DMD,
 179                                    0x00, 0x20);
 180        if (ret)
 181                return ret;
 182
 183        ret = tnrdmd->io->read_regs(tnrdmd->io,
 184                                    CXD2880_IO_TGT_DMD,
 185                                    0x6f, data, 1);
 186        if (ret)
 187                return ret;
 188
 189        period_exp = data[0] & 0x0f;
 190
 191        *pre_bit_count = (1U << period_exp) * n_ldpc;
 192
 193        return 0;
 194}
 195
 196static int cxd2880_post_bit_err_t(struct cxd2880_tnrdmd *tnrdmd,
 197                                  u32 *post_bit_err,
 198                                  u32 *post_bit_count)
 199{
 200        u8 rdata[3];
 201        u32 bit_error = 0;
 202        u32 period_exp = 0;
 203        int ret;
 204
 205        if (!tnrdmd || !post_bit_err || !post_bit_count)
 206                return -EINVAL;
 207
 208        if (tnrdmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
 209                return -EINVAL;
 210
 211        if (tnrdmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
 212                return -EINVAL;
 213
 214        if (tnrdmd->sys != CXD2880_DTV_SYS_DVBT)
 215                return -EINVAL;
 216
 217        ret = tnrdmd->io->write_reg(tnrdmd->io,
 218                                    CXD2880_IO_TGT_DMD,
 219                                    0x00, 0x0d);
 220        if (ret)
 221                return ret;
 222
 223        ret = tnrdmd->io->read_regs(tnrdmd->io,
 224                                    CXD2880_IO_TGT_DMD,
 225                                    0x15, rdata, 3);
 226        if (ret)
 227                return ret;
 228
 229        if ((rdata[0] & 0x40) == 0)
 230                return -EAGAIN;
 231
 232        *post_bit_err = ((rdata[0] & 0x3f) << 16) | (rdata[1] << 8) | rdata[2];
 233
 234        ret = tnrdmd->io->write_reg(tnrdmd->io,
 235                                    CXD2880_IO_TGT_DMD,
 236                                    0x00, 0x10);
 237        if (ret)
 238                return ret;
 239
 240        ret = tnrdmd->io->read_regs(tnrdmd->io,
 241                                    CXD2880_IO_TGT_DMD,
 242                                    0x60, rdata, 1);
 243        if (ret)
 244                return ret;
 245
 246        period_exp = (rdata[0] & 0x1f);
 247
 248        if (period_exp <= 11 && (bit_error > (1U << period_exp) * 204 * 8))
 249                return -EAGAIN;
 250
 251        *post_bit_count = (1U << period_exp) * 204 * 8;
 252
 253        return 0;
 254}
 255
 256static int cxd2880_post_bit_err_t2(struct cxd2880_tnrdmd *tnrdmd,
 257                                   u32 *post_bit_err,
 258                                   u32 *post_bit_count)
 259{
 260        u32 period_exp = 0;
 261        u32 n_bch = 0;
 262        u8 data[3];
 263        enum cxd2880_dvbt2_plp_fec plp_fec_type =
 264                CXD2880_DVBT2_FEC_LDPC_16K;
 265        enum cxd2880_dvbt2_plp_code_rate plp_code_rate =
 266                CXD2880_DVBT2_R1_2;
 267        int ret;
 268        static const u16 n_bch_bits_lookup[2][8] = {
 269                {7200, 9720, 10800, 11880, 12600, 13320, 5400, 6480},
 270                {32400, 38880, 43200, 48600, 51840, 54000, 21600, 25920}
 271        };
 272
 273        if (!tnrdmd || !post_bit_err || !post_bit_count)
 274                return -EINVAL;
 275
 276        if (tnrdmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
 277                return -EINVAL;
 278
 279        if (tnrdmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
 280                return -EINVAL;
 281
 282        if (tnrdmd->sys != CXD2880_DTV_SYS_DVBT2)
 283                return -EINVAL;
 284
 285        ret = slvt_freeze_reg(tnrdmd);
 286        if (ret)
 287                return ret;
 288
 289        ret = tnrdmd->io->write_reg(tnrdmd->io,
 290                                    CXD2880_IO_TGT_DMD,
 291                                    0x00, 0x0b);
 292        if (ret) {
 293                slvt_unfreeze_reg(tnrdmd);
 294                return ret;
 295        }
 296
 297        ret = tnrdmd->io->read_regs(tnrdmd->io,
 298                                    CXD2880_IO_TGT_DMD,
 299                                    0x15, data, 3);
 300        if (ret) {
 301                slvt_unfreeze_reg(tnrdmd);
 302                return ret;
 303        }
 304
 305        if (!(data[0] & 0x40)) {
 306                slvt_unfreeze_reg(tnrdmd);
 307                return -EAGAIN;
 308        }
 309
 310        *post_bit_err =
 311                ((data[0] & 0x3f) << 16) | (data[1] << 8) | data[2];
 312
 313        ret = tnrdmd->io->read_regs(tnrdmd->io,
 314                                    CXD2880_IO_TGT_DMD,
 315                                    0x9d, data, 1);
 316        if (ret) {
 317                slvt_unfreeze_reg(tnrdmd);
 318                return ret;
 319        }
 320
 321        plp_code_rate =
 322        (enum cxd2880_dvbt2_plp_code_rate)(data[0] & 0x07);
 323
 324        ret = tnrdmd->io->read_regs(tnrdmd->io,
 325                                    CXD2880_IO_TGT_DMD,
 326                                    0xa0, data, 1);
 327        if (ret) {
 328                slvt_unfreeze_reg(tnrdmd);
 329                return ret;
 330        }
 331
 332        plp_fec_type = (enum cxd2880_dvbt2_plp_fec)(data[0] & 0x03);
 333
 334        slvt_unfreeze_reg(tnrdmd);
 335
 336        ret = tnrdmd->io->write_reg(tnrdmd->io,
 337                                    CXD2880_IO_TGT_DMD,
 338                                    0x00, 0x20);
 339        if (ret)
 340                return ret;
 341
 342        ret = tnrdmd->io->read_regs(tnrdmd->io,
 343                                    CXD2880_IO_TGT_DMD,
 344                                    0x72, data, 1);
 345        if (ret)
 346                return ret;
 347
 348        period_exp = data[0] & 0x0f;
 349
 350        if (plp_fec_type > CXD2880_DVBT2_FEC_LDPC_64K ||
 351            plp_code_rate > CXD2880_DVBT2_R2_5)
 352                return -EAGAIN;
 353
 354        n_bch = n_bch_bits_lookup[plp_fec_type][plp_code_rate];
 355
 356        if (*post_bit_err > ((1U << period_exp) * n_bch))
 357                return -EAGAIN;
 358
 359        *post_bit_count = (1U << period_exp) * n_bch;
 360
 361        return 0;
 362}
 363
 364static int cxd2880_read_block_err_t(struct cxd2880_tnrdmd *tnrdmd,
 365                                    u32 *block_err,
 366                                    u32 *block_count)
 367{
 368        u8 rdata[3];
 369        int ret;
 370
 371        if (!tnrdmd || !block_err || !block_count)
 372                return -EINVAL;
 373
 374        if (tnrdmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
 375                return -EINVAL;
 376
 377        if (tnrdmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
 378                return -EINVAL;
 379
 380        if (tnrdmd->sys != CXD2880_DTV_SYS_DVBT)
 381                return -EINVAL;
 382
 383        ret = tnrdmd->io->write_reg(tnrdmd->io,
 384                                    CXD2880_IO_TGT_DMD,
 385                                    0x00, 0x0d);
 386        if (ret)
 387                return ret;
 388
 389        ret = tnrdmd->io->read_regs(tnrdmd->io,
 390                                    CXD2880_IO_TGT_DMD,
 391                                    0x18, rdata, 3);
 392        if (ret)
 393                return ret;
 394
 395        if ((rdata[0] & 0x01) == 0)
 396                return -EAGAIN;
 397
 398        *block_err = (rdata[1] << 8) | rdata[2];
 399
 400        ret = tnrdmd->io->write_reg(tnrdmd->io,
 401                                    CXD2880_IO_TGT_DMD,
 402                                    0x00, 0x10);
 403        if (ret)
 404                return ret;
 405
 406        ret = tnrdmd->io->read_regs(tnrdmd->io,
 407                                    CXD2880_IO_TGT_DMD,
 408                                    0x5c, rdata, 1);
 409        if (ret)
 410                return ret;
 411
 412        *block_count = 1U << (rdata[0] & 0x0f);
 413
 414        if ((*block_count == 0) || (*block_err > *block_count))
 415                return -EAGAIN;
 416
 417        return 0;
 418}
 419
 420static int cxd2880_read_block_err_t2(struct cxd2880_tnrdmd *tnrdmd,
 421                                     u32 *block_err,
 422                                     u32 *block_count)
 423{
 424        u8 rdata[3];
 425        int ret;
 426
 427        if (!tnrdmd || !block_err || !block_count)
 428                return -EINVAL;
 429
 430        if (tnrdmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
 431                return -EINVAL;
 432
 433        if (tnrdmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
 434                return -EINVAL;
 435        if (tnrdmd->sys != CXD2880_DTV_SYS_DVBT2)
 436                return -EINVAL;
 437
 438        ret = tnrdmd->io->write_reg(tnrdmd->io,
 439                                    CXD2880_IO_TGT_DMD,
 440                                    0x00, 0x0b);
 441        if (ret)
 442                return ret;
 443
 444        ret = tnrdmd->io->read_regs(tnrdmd->io,
 445                                    CXD2880_IO_TGT_DMD,
 446                                    0x18, rdata, 3);
 447        if (ret)
 448                return ret;
 449
 450        if ((rdata[0] & 0x01) == 0)
 451                return -EAGAIN;
 452
 453        *block_err = (rdata[1] << 8) | rdata[2];
 454
 455        ret = tnrdmd->io->write_reg(tnrdmd->io,
 456                                    CXD2880_IO_TGT_DMD,
 457                                    0x00, 0x24);
 458        if (ret)
 459                return ret;
 460
 461        ret = tnrdmd->io->read_regs(tnrdmd->io,
 462                                    CXD2880_IO_TGT_DMD,
 463                                    0xdc, rdata, 1);
 464        if (ret)
 465                return ret;
 466
 467        *block_count = 1U << (rdata[0] & 0x0f);
 468
 469        if ((*block_count == 0) || (*block_err > *block_count))
 470                return -EAGAIN;
 471
 472        return 0;
 473}
 474
 475static void cxd2880_release(struct dvb_frontend *fe)
 476{
 477        struct cxd2880_priv *priv = NULL;
 478
 479        if (!fe) {
 480                pr_err("invalid arg.\n");
 481                return;
 482        }
 483        priv = fe->demodulator_priv;
 484        kfree(priv);
 485}
 486
 487static int cxd2880_init(struct dvb_frontend *fe)
 488{
 489        int ret;
 490        struct cxd2880_priv *priv = NULL;
 491        struct cxd2880_tnrdmd_create_param create_param;
 492
 493        if (!fe) {
 494                pr_err("invalid arg.\n");
 495                return -EINVAL;
 496        }
 497
 498        priv = fe->demodulator_priv;
 499
 500        create_param.ts_output_if = CXD2880_TNRDMD_TSOUT_IF_SPI;
 501        create_param.xtal_share_type = CXD2880_TNRDMD_XTAL_SHARE_NONE;
 502        create_param.en_internal_ldo = 1;
 503        create_param.xosc_cap = 18;
 504        create_param.xosc_i = 8;
 505        create_param.stationary_use = 1;
 506
 507        mutex_lock(priv->spi_mutex);
 508        if (priv->tnrdmd.io != &priv->regio) {
 509                ret = cxd2880_tnrdmd_create(&priv->tnrdmd,
 510                                            &priv->regio, &create_param);
 511                if (ret) {
 512                        mutex_unlock(priv->spi_mutex);
 513                        pr_info("cxd2880 tnrdmd create failed %d\n", ret);
 514                        return ret;
 515                }
 516        }
 517        ret = cxd2880_integ_init(&priv->tnrdmd);
 518        if (ret) {
 519                mutex_unlock(priv->spi_mutex);
 520                pr_err("cxd2880 integ init failed %d\n", ret);
 521                return ret;
 522        }
 523
 524        ret = cxd2880_tnrdmd_set_cfg(&priv->tnrdmd,
 525                                     CXD2880_TNRDMD_CFG_TSPIN_CURRENT,
 526                                     0x00);
 527        if (ret) {
 528                mutex_unlock(priv->spi_mutex);
 529                pr_err("cxd2880 set config failed %d\n", ret);
 530                return ret;
 531        }
 532        mutex_unlock(priv->spi_mutex);
 533
 534        pr_debug("OK.\n");
 535
 536        return ret;
 537}
 538
 539static int cxd2880_sleep(struct dvb_frontend *fe)
 540{
 541        int ret;
 542        struct cxd2880_priv *priv = NULL;
 543
 544        if (!fe) {
 545                pr_err("invalid arg\n");
 546                return -EINVAL;
 547        }
 548
 549        priv = fe->demodulator_priv;
 550
 551        mutex_lock(priv->spi_mutex);
 552        ret = cxd2880_tnrdmd_sleep(&priv->tnrdmd);
 553        mutex_unlock(priv->spi_mutex);
 554
 555        pr_debug("tnrdmd_sleep ret %d\n", ret);
 556
 557        return ret;
 558}
 559
 560static int cxd2880_read_signal_strength(struct dvb_frontend *fe,
 561                                        u16 *strength)
 562{
 563        int ret;
 564        struct cxd2880_priv *priv = NULL;
 565        struct dtv_frontend_properties *c = NULL;
 566        int level = 0;
 567
 568        if (!fe || !strength) {
 569                pr_err("invalid arg\n");
 570                return -EINVAL;
 571        }
 572
 573        priv = fe->demodulator_priv;
 574        c = &fe->dtv_property_cache;
 575
 576        mutex_lock(priv->spi_mutex);
 577        if (c->delivery_system == SYS_DVBT ||
 578            c->delivery_system == SYS_DVBT2) {
 579                ret = cxd2880_tnrdmd_mon_rf_lvl(&priv->tnrdmd, &level);
 580        } else {
 581                pr_debug("invalid system\n");
 582                mutex_unlock(priv->spi_mutex);
 583                return -EINVAL;
 584        }
 585        mutex_unlock(priv->spi_mutex);
 586
 587        level /= 125;
 588        /*
 589         * level should be between -105dBm and -30dBm.
 590         * E.g. they should be between:
 591         * -105000/125 = -840 and -30000/125 = -240
 592         */
 593        level = clamp(level, -840, -240);
 594        /* scale value to 0x0000-0xffff */
 595        *strength = ((level + 840) * 0xffff) / (-240 + 840);
 596
 597        if (ret)
 598                pr_debug("ret = %d\n", ret);
 599
 600        return ret;
 601}
 602
 603static int cxd2880_read_snr(struct dvb_frontend *fe, u16 *snr)
 604{
 605        int ret;
 606        int snrvalue = 0;
 607        struct cxd2880_priv *priv = NULL;
 608        struct dtv_frontend_properties *c = NULL;
 609
 610        if (!fe || !snr) {
 611                pr_err("invalid arg\n");
 612                return -EINVAL;
 613        }
 614
 615        priv = fe->demodulator_priv;
 616        c = &fe->dtv_property_cache;
 617
 618        mutex_lock(priv->spi_mutex);
 619        if (c->delivery_system == SYS_DVBT) {
 620                ret = cxd2880_tnrdmd_dvbt_mon_snr(&priv->tnrdmd,
 621                                                  &snrvalue);
 622        } else if (c->delivery_system == SYS_DVBT2) {
 623                ret = cxd2880_tnrdmd_dvbt2_mon_snr(&priv->tnrdmd,
 624                                                   &snrvalue);
 625        } else {
 626                pr_err("invalid system\n");
 627                mutex_unlock(priv->spi_mutex);
 628                return -EINVAL;
 629        }
 630        mutex_unlock(priv->spi_mutex);
 631
 632        if (snrvalue < 0)
 633                snrvalue = 0;
 634        *snr = snrvalue;
 635
 636        if (ret)
 637                pr_debug("ret = %d\n", ret);
 638
 639        return ret;
 640}
 641
 642static int cxd2880_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
 643{
 644        int ret;
 645        struct cxd2880_priv *priv = NULL;
 646        struct dtv_frontend_properties *c = NULL;
 647
 648        if (!fe || !ucblocks) {
 649                pr_err("invalid arg\n");
 650                return -EINVAL;
 651        }
 652
 653        priv = fe->demodulator_priv;
 654        c = &fe->dtv_property_cache;
 655
 656        mutex_lock(priv->spi_mutex);
 657        if (c->delivery_system == SYS_DVBT) {
 658                ret = cxd2880_tnrdmd_dvbt_mon_packet_error_number(&priv->tnrdmd,
 659                                                                  ucblocks);
 660        } else if (c->delivery_system == SYS_DVBT2) {
 661                ret = cxd2880_tnrdmd_dvbt2_mon_packet_error_number(&priv->tnrdmd,
 662                                                                   ucblocks);
 663        } else {
 664                pr_err("invalid system\n");
 665                mutex_unlock(priv->spi_mutex);
 666                return -EINVAL;
 667        }
 668        mutex_unlock(priv->spi_mutex);
 669
 670        if (ret)
 671                pr_debug("ret = %d\n", ret);
 672
 673        return ret;
 674}
 675
 676static int cxd2880_read_ber(struct dvb_frontend *fe, u32 *ber)
 677{
 678        *ber = 0;
 679
 680        return 0;
 681}
 682
 683static int cxd2880_set_ber_per_period_t(struct dvb_frontend *fe)
 684{
 685        int ret;
 686        struct cxd2880_priv *priv;
 687        struct cxd2880_dvbt_tpsinfo info;
 688        enum cxd2880_dtv_bandwidth bw;
 689        u32 pre_ber_rate = 0;
 690        u32 post_ber_rate = 0;
 691        u32 ucblock_rate = 0;
 692        u32 mes_exp = 0;
 693        static const int cr_table[5] = {31500, 42000, 47250, 52500, 55125};
 694        static const int denominator_tbl[4] = {125664, 129472, 137088, 152320};
 695
 696        if (!fe) {
 697                pr_err("invalid arg\n");
 698                return -EINVAL;
 699        }
 700
 701        priv = fe->demodulator_priv;
 702        bw = priv->dvbt_tune_param.bandwidth;
 703
 704        ret = cxd2880_tnrdmd_dvbt_mon_tps_info(&priv->tnrdmd,
 705                                               &info);
 706        if (ret) {
 707                pr_err("tps monitor error ret = %d\n", ret);
 708                info.hierarchy = CXD2880_DVBT_HIERARCHY_NON;
 709                info.constellation = CXD2880_DVBT_CONSTELLATION_QPSK;
 710                info.guard = CXD2880_DVBT_GUARD_1_4;
 711                info.rate_hp = CXD2880_DVBT_CODERATE_1_2;
 712                info.rate_lp = CXD2880_DVBT_CODERATE_1_2;
 713        }
 714
 715        if (info.hierarchy == CXD2880_DVBT_HIERARCHY_NON) {
 716                pre_ber_rate = 63000000 * bw * (info.constellation * 2 + 2) /
 717                               denominator_tbl[info.guard];
 718
 719                post_ber_rate = 1000 * cr_table[info.rate_hp] * bw *
 720                                (info.constellation * 2 + 2) /
 721                                denominator_tbl[info.guard];
 722
 723                ucblock_rate = 875 * cr_table[info.rate_hp] * bw *
 724                               (info.constellation * 2 + 2) /
 725                               denominator_tbl[info.guard];
 726        } else {
 727                u8 data = 0;
 728                struct cxd2880_tnrdmd *tnrdmd = &priv->tnrdmd;
 729
 730                ret = tnrdmd->io->write_reg(tnrdmd->io,
 731                                            CXD2880_IO_TGT_DMD,
 732                                            0x00, 0x10);
 733                if (!ret) {
 734                        ret = tnrdmd->io->read_regs(tnrdmd->io,
 735                                                    CXD2880_IO_TGT_DMD,
 736                                                    0x67, &data, 1);
 737                        if (ret)
 738                                data = 0x00;
 739                } else {
 740                        data = 0x00;
 741                }
 742
 743                if (data & 0x01) { /* Low priority */
 744                        pre_ber_rate =
 745                                63000000 * bw * (info.constellation * 2 + 2) /
 746                                denominator_tbl[info.guard];
 747
 748                        post_ber_rate = 1000 * cr_table[info.rate_lp] * bw *
 749                                        (info.constellation * 2 + 2) /
 750                                        denominator_tbl[info.guard];
 751
 752                        ucblock_rate = (1000 * 7 / 8) * cr_table[info.rate_lp] *
 753                                       bw * (info.constellation * 2 + 2) /
 754                                       denominator_tbl[info.guard];
 755                } else { /* High priority */
 756                        pre_ber_rate =
 757                                63000000 * bw * 2 / denominator_tbl[info.guard];
 758
 759                        post_ber_rate = 1000 * cr_table[info.rate_hp] * bw * 2 /
 760                                        denominator_tbl[info.guard];
 761
 762                        ucblock_rate = (1000 * 7 / 8) * cr_table[info.rate_hp] *
 763                                        bw * 2 / denominator_tbl[info.guard];
 764                }
 765        }
 766
 767        mes_exp = pre_ber_rate < 8192 ? 8 : intlog2(pre_ber_rate) >> 24;
 768        priv->pre_ber_interval =
 769                ((1U << mes_exp) * 1000 + (pre_ber_rate / 2)) /
 770                pre_ber_rate;
 771        cxd2880_tnrdmd_set_cfg(&priv->tnrdmd,
 772                               CXD2880_TNRDMD_CFG_DVBT_VBER_PERIOD,
 773                               mes_exp == 8 ? 0 : mes_exp - 12);
 774
 775        mes_exp = intlog2(post_ber_rate) >> 24;
 776        priv->post_ber_interval =
 777                ((1U << mes_exp) * 1000 + (post_ber_rate / 2)) /
 778                post_ber_rate;
 779        cxd2880_tnrdmd_set_cfg(&priv->tnrdmd,
 780                               CXD2880_TNRDMD_CFG_DVBT_BERN_PERIOD,
 781                               mes_exp);
 782
 783        mes_exp = intlog2(ucblock_rate) >> 24;
 784        priv->ucblock_interval =
 785                ((1U << mes_exp) * 1000 + (ucblock_rate / 2)) /
 786                ucblock_rate;
 787        cxd2880_tnrdmd_set_cfg(&priv->tnrdmd,
 788                               CXD2880_TNRDMD_CFG_DVBT_PER_MES,
 789                               mes_exp);
 790
 791        return 0;
 792}
 793
 794static int cxd2880_set_ber_per_period_t2(struct dvb_frontend *fe)
 795{
 796        int ret;
 797        struct cxd2880_priv *priv;
 798        struct cxd2880_dvbt2_l1pre l1pre;
 799        struct cxd2880_dvbt2_l1post l1post;
 800        struct cxd2880_dvbt2_plp plp;
 801        struct cxd2880_dvbt2_bbheader bbheader;
 802        enum cxd2880_dtv_bandwidth bw = CXD2880_DTV_BW_1_7_MHZ;
 803        u32 pre_ber_rate = 0;
 804        u32 post_ber_rate = 0;
 805        u32 ucblock_rate = 0;
 806        u32 mes_exp = 0;
 807        u32 term_a = 0;
 808        u32 term_b = 0;
 809        u32 denominator = 0;
 810        static const u32 gi_tbl[7] = {32, 64, 128, 256, 8, 152, 76};
 811        static const u8 n_tbl[6] = {8, 2, 4, 16, 1, 1};
 812        static const u8 mode_tbl[6] = {2, 8, 4, 1, 16, 32};
 813        static const u32 kbch_tbl[2][8] = {
 814                {6952, 9472, 10552, 11632, 12352, 13072, 5152, 6232},
 815                {32128, 38608, 42960, 48328, 51568, 53760, 0, 0}
 816        };
 817
 818        if (!fe) {
 819                pr_err("invalid arg\n");
 820                return -EINVAL;
 821        }
 822
 823        priv = fe->demodulator_priv;
 824        bw = priv->dvbt2_tune_param.bandwidth;
 825
 826        ret = cxd2880_tnrdmd_dvbt2_mon_l1_pre(&priv->tnrdmd, &l1pre);
 827        if (ret) {
 828                pr_info("l1 pre error\n");
 829                goto error_ber_setting;
 830        }
 831
 832        ret = cxd2880_tnrdmd_dvbt2_mon_active_plp(&priv->tnrdmd,
 833                                                  CXD2880_DVBT2_PLP_DATA, &plp);
 834        if (ret) {
 835                pr_info("plp info error\n");
 836                goto error_ber_setting;
 837        }
 838
 839        ret = cxd2880_tnrdmd_dvbt2_mon_l1_post(&priv->tnrdmd, &l1post);
 840        if (ret) {
 841                pr_info("l1 post error\n");
 842                goto error_ber_setting;
 843        }
 844
 845        term_a =
 846                (mode_tbl[l1pre.fft_mode] * (1024 + gi_tbl[l1pre.gi])) *
 847                (l1pre.num_symbols + n_tbl[l1pre.fft_mode]) + 2048;
 848
 849        if (l1pre.mixed && l1post.fef_intvl) {
 850                term_b = (l1post.fef_length + (l1post.fef_intvl / 2)) /
 851                         l1post.fef_intvl;
 852        } else {
 853                term_b = 0;
 854        }
 855
 856        switch (bw) {
 857        case CXD2880_DTV_BW_1_7_MHZ:
 858                denominator = ((term_a + term_b) * 71 + (131 / 2)) / 131;
 859                break;
 860        case CXD2880_DTV_BW_5_MHZ:
 861                denominator = ((term_a + term_b) * 7 + 20) / 40;
 862                break;
 863        case CXD2880_DTV_BW_6_MHZ:
 864                denominator = ((term_a + term_b) * 7 + 24) / 48;
 865                break;
 866        case CXD2880_DTV_BW_7_MHZ:
 867                denominator = ((term_a + term_b) + 4) / 8;
 868                break;
 869        case CXD2880_DTV_BW_8_MHZ:
 870        default:
 871                denominator = ((term_a + term_b) * 7 + 32) / 64;
 872                break;
 873        }
 874
 875        if (plp.til_type && plp.til_len) {
 876                pre_ber_rate =
 877                        (plp.num_blocks_max * 1000000 + (denominator / 2)) /
 878                        denominator;
 879                pre_ber_rate = (pre_ber_rate + (plp.til_len / 2)) /
 880                               plp.til_len;
 881        } else {
 882                pre_ber_rate =
 883                        (plp.num_blocks_max * 1000000 + (denominator / 2)) /
 884                        denominator;
 885        }
 886
 887        post_ber_rate = pre_ber_rate;
 888
 889        mes_exp = intlog2(pre_ber_rate) >> 24;
 890        priv->pre_ber_interval =
 891                ((1U << mes_exp) * 1000 + (pre_ber_rate / 2)) /
 892                pre_ber_rate;
 893        cxd2880_tnrdmd_set_cfg(&priv->tnrdmd,
 894                               CXD2880_TNRDMD_CFG_DVBT2_LBER_MES,
 895                               mes_exp);
 896
 897        mes_exp = intlog2(post_ber_rate) >> 24;
 898        priv->post_ber_interval =
 899                ((1U << mes_exp) * 1000 + (post_ber_rate / 2)) /
 900                post_ber_rate;
 901        cxd2880_tnrdmd_set_cfg(&priv->tnrdmd,
 902                               CXD2880_TNRDMD_CFG_DVBT2_BBER_MES,
 903                               mes_exp);
 904
 905        ret = cxd2880_tnrdmd_dvbt2_mon_bbheader(&priv->tnrdmd,
 906                                                CXD2880_DVBT2_PLP_DATA,
 907                                                &bbheader);
 908        if (ret) {
 909                pr_info("bb header error\n");
 910                goto error_ucblock_setting;
 911        }
 912
 913        if (bbheader.plp_mode == CXD2880_DVBT2_PLP_MODE_NM) {
 914                if (!bbheader.issy_indicator) {
 915                        ucblock_rate =
 916                                (pre_ber_rate * kbch_tbl[plp.fec][plp.plp_cr] +
 917                                752) / 1504;
 918                } else {
 919                        ucblock_rate =
 920                                (pre_ber_rate * kbch_tbl[plp.fec][plp.plp_cr] +
 921                                764) / 1528;
 922                }
 923        } else if (bbheader.plp_mode == CXD2880_DVBT2_PLP_MODE_HEM) {
 924                ucblock_rate =
 925                        (pre_ber_rate * kbch_tbl[plp.fec][plp.plp_cr] + 748) /
 926                        1496;
 927        } else {
 928                pr_info("plp mode is not Normal or HEM\n");
 929                goto error_ucblock_setting;
 930        }
 931
 932        mes_exp = intlog2(ucblock_rate) >> 24;
 933        priv->ucblock_interval =
 934                ((1U << mes_exp) * 1000 + (ucblock_rate / 2)) /
 935                ucblock_rate;
 936        cxd2880_tnrdmd_set_cfg(&priv->tnrdmd,
 937                               CXD2880_TNRDMD_CFG_DVBT2_PER_MES,
 938                               mes_exp);
 939
 940        return 0;
 941
 942error_ber_setting:
 943        priv->pre_ber_interval = 1000;
 944        cxd2880_tnrdmd_set_cfg(&priv->tnrdmd,
 945                                     CXD2880_TNRDMD_CFG_DVBT2_LBER_MES, 0);
 946
 947        priv->post_ber_interval = 1000;
 948        cxd2880_tnrdmd_set_cfg(&priv->tnrdmd,
 949                               CXD2880_TNRDMD_CFG_DVBT2_BBER_MES, 0);
 950
 951error_ucblock_setting:
 952        priv->ucblock_interval = 1000;
 953        cxd2880_tnrdmd_set_cfg(&priv->tnrdmd,
 954                               CXD2880_TNRDMD_CFG_DVBT2_PER_MES, 8);
 955
 956        return 0;
 957}
 958
 959static int cxd2880_dvbt_tune(struct cxd2880_tnrdmd *tnr_dmd,
 960                             struct cxd2880_dvbt_tune_param
 961                             *tune_param)
 962{
 963        int ret;
 964
 965        if (!tnr_dmd || !tune_param)
 966                return -EINVAL;
 967
 968        if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
 969                return -EINVAL;
 970
 971        if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP &&
 972            tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
 973                return -EINVAL;
 974
 975        atomic_set(&tnr_dmd->cancel, 0);
 976
 977        if (tune_param->bandwidth != CXD2880_DTV_BW_5_MHZ &&
 978            tune_param->bandwidth != CXD2880_DTV_BW_6_MHZ &&
 979            tune_param->bandwidth != CXD2880_DTV_BW_7_MHZ &&
 980            tune_param->bandwidth != CXD2880_DTV_BW_8_MHZ) {
 981                return -ENOTTY;
 982        }
 983
 984        ret = cxd2880_tnrdmd_dvbt_tune1(tnr_dmd, tune_param);
 985        if (ret)
 986                return ret;
 987
 988        usleep_range(CXD2880_TNRDMD_WAIT_AGC_STABLE * 10000,
 989                     CXD2880_TNRDMD_WAIT_AGC_STABLE * 10000 + 1000);
 990
 991        return cxd2880_tnrdmd_dvbt_tune2(tnr_dmd, tune_param);
 992}
 993
 994static int cxd2880_dvbt2_tune(struct cxd2880_tnrdmd *tnr_dmd,
 995                              struct cxd2880_dvbt2_tune_param
 996                              *tune_param)
 997{
 998        int ret;
 999
1000        if (!tnr_dmd || !tune_param)
1001                return -EINVAL;
1002
1003        if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
1004                return -EINVAL;
1005
1006        if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP &&
1007            tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
1008                return -EINVAL;
1009
1010        atomic_set(&tnr_dmd->cancel, 0);
1011
1012        if (tune_param->bandwidth != CXD2880_DTV_BW_1_7_MHZ &&
1013            tune_param->bandwidth != CXD2880_DTV_BW_5_MHZ &&
1014            tune_param->bandwidth != CXD2880_DTV_BW_6_MHZ &&
1015            tune_param->bandwidth != CXD2880_DTV_BW_7_MHZ &&
1016            tune_param->bandwidth != CXD2880_DTV_BW_8_MHZ) {
1017                return -ENOTTY;
1018        }
1019
1020        if (tune_param->profile != CXD2880_DVBT2_PROFILE_BASE &&
1021            tune_param->profile != CXD2880_DVBT2_PROFILE_LITE)
1022                return -EINVAL;
1023
1024        ret = cxd2880_tnrdmd_dvbt2_tune1(tnr_dmd, tune_param);
1025        if (ret)
1026                return ret;
1027
1028        usleep_range(CXD2880_TNRDMD_WAIT_AGC_STABLE * 10000,
1029                     CXD2880_TNRDMD_WAIT_AGC_STABLE * 10000 + 1000);
1030
1031        return cxd2880_tnrdmd_dvbt2_tune2(tnr_dmd, tune_param);
1032}
1033
1034static int cxd2880_set_frontend(struct dvb_frontend *fe)
1035{
1036        int ret;
1037        struct dtv_frontend_properties *c;
1038        struct cxd2880_priv *priv;
1039        enum cxd2880_dtv_bandwidth bw = CXD2880_DTV_BW_1_7_MHZ;
1040
1041        if (!fe) {
1042                pr_err("invalid arg\n");
1043                return -EINVAL;
1044        }
1045
1046        priv = fe->demodulator_priv;
1047        c = &fe->dtv_property_cache;
1048
1049        c->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1050        c->pre_bit_error.stat[0].uvalue = 0;
1051        c->pre_bit_error.len = 1;
1052        c->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1053        c->pre_bit_count.stat[0].uvalue = 0;
1054        c->pre_bit_count.len = 1;
1055        c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1056        c->post_bit_error.stat[0].uvalue = 0;
1057        c->post_bit_error.len = 1;
1058        c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1059        c->post_bit_count.stat[0].uvalue = 0;
1060        c->post_bit_count.len = 1;
1061        c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1062        c->block_error.stat[0].uvalue = 0;
1063        c->block_error.len = 1;
1064        c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1065        c->block_count.stat[0].uvalue = 0;
1066        c->block_count.len = 1;
1067
1068        switch (c->bandwidth_hz) {
1069        case 1712000:
1070                bw = CXD2880_DTV_BW_1_7_MHZ;
1071                break;
1072        case 5000000:
1073                bw = CXD2880_DTV_BW_5_MHZ;
1074                break;
1075        case 6000000:
1076                bw = CXD2880_DTV_BW_6_MHZ;
1077                break;
1078        case 7000000:
1079                bw = CXD2880_DTV_BW_7_MHZ;
1080                break;
1081        case 8000000:
1082                bw = CXD2880_DTV_BW_8_MHZ;
1083                break;
1084        default:
1085                return -EINVAL;
1086        }
1087
1088        priv->s = 0;
1089
1090        pr_info("sys:%d freq:%d bw:%d\n",
1091                c->delivery_system, c->frequency, bw);
1092        mutex_lock(priv->spi_mutex);
1093        if (c->delivery_system == SYS_DVBT) {
1094                priv->tnrdmd.sys = CXD2880_DTV_SYS_DVBT;
1095                priv->dvbt_tune_param.center_freq_khz = c->frequency / 1000;
1096                priv->dvbt_tune_param.bandwidth = bw;
1097                priv->dvbt_tune_param.profile = CXD2880_DVBT_PROFILE_HP;
1098                ret = cxd2880_dvbt_tune(&priv->tnrdmd,
1099                                        &priv->dvbt_tune_param);
1100        } else if (c->delivery_system == SYS_DVBT2) {
1101                priv->tnrdmd.sys = CXD2880_DTV_SYS_DVBT2;
1102                priv->dvbt2_tune_param.center_freq_khz = c->frequency / 1000;
1103                priv->dvbt2_tune_param.bandwidth = bw;
1104                priv->dvbt2_tune_param.data_plp_id = (u16)c->stream_id;
1105                priv->dvbt2_tune_param.profile = CXD2880_DVBT2_PROFILE_BASE;
1106                ret = cxd2880_dvbt2_tune(&priv->tnrdmd,
1107                                         &priv->dvbt2_tune_param);
1108        } else {
1109                pr_err("invalid system\n");
1110                mutex_unlock(priv->spi_mutex);
1111                return -EINVAL;
1112        }
1113        mutex_unlock(priv->spi_mutex);
1114
1115        pr_info("tune result %d\n", ret);
1116
1117        return ret;
1118}
1119
1120static int cxd2880_get_stats(struct dvb_frontend *fe,
1121                             enum fe_status status)
1122{
1123        struct cxd2880_priv *priv = NULL;
1124        struct dtv_frontend_properties *c = NULL;
1125        u32 pre_bit_err = 0, pre_bit_count = 0;
1126        u32 post_bit_err = 0, post_bit_count = 0;
1127        u32 block_err = 0, block_count = 0;
1128        int ret;
1129
1130        if (!fe) {
1131                pr_err("invalid arg\n");
1132                return -EINVAL;
1133        }
1134
1135        priv = fe->demodulator_priv;
1136        c = &fe->dtv_property_cache;
1137
1138        if (!(status & FE_HAS_LOCK) || !(status & FE_HAS_CARRIER)) {
1139                c->pre_bit_error.len = 1;
1140                c->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1141                c->pre_bit_count.len = 1;
1142                c->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1143                c->post_bit_error.len = 1;
1144                c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1145                c->post_bit_count.len = 1;
1146                c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1147                c->block_error.len = 1;
1148                c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1149                c->block_count.len = 1;
1150                c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1151
1152                return 0;
1153        }
1154
1155        if (time_after(jiffies, priv->pre_ber_update)) {
1156                priv->pre_ber_update =
1157                         jiffies + msecs_to_jiffies(priv->pre_ber_interval);
1158                if (c->delivery_system == SYS_DVBT) {
1159                        mutex_lock(priv->spi_mutex);
1160                        ret = cxd2880_pre_bit_err_t(&priv->tnrdmd,
1161                                                    &pre_bit_err,
1162                                                    &pre_bit_count);
1163                        mutex_unlock(priv->spi_mutex);
1164                } else if (c->delivery_system == SYS_DVBT2) {
1165                        mutex_lock(priv->spi_mutex);
1166                        ret = cxd2880_pre_bit_err_t2(&priv->tnrdmd,
1167                                                     &pre_bit_err,
1168                                                     &pre_bit_count);
1169                        mutex_unlock(priv->spi_mutex);
1170                } else {
1171                        return -EINVAL;
1172                }
1173
1174                if (!ret) {
1175                        c->pre_bit_error.len = 1;
1176                        c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
1177                        c->pre_bit_error.stat[0].uvalue += pre_bit_err;
1178                        c->pre_bit_count.len = 1;
1179                        c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
1180                        c->pre_bit_count.stat[0].uvalue += pre_bit_count;
1181                } else {
1182                        c->pre_bit_error.len = 1;
1183                        c->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1184                        c->pre_bit_count.len = 1;
1185                        c->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1186                        pr_debug("pre_bit_error_t failed %d\n", ret);
1187                }
1188        }
1189
1190        if (time_after(jiffies, priv->post_ber_update)) {
1191                priv->post_ber_update =
1192                        jiffies + msecs_to_jiffies(priv->post_ber_interval);
1193                if (c->delivery_system == SYS_DVBT) {
1194                        mutex_lock(priv->spi_mutex);
1195                        ret = cxd2880_post_bit_err_t(&priv->tnrdmd,
1196                                                     &post_bit_err,
1197                                                     &post_bit_count);
1198                        mutex_unlock(priv->spi_mutex);
1199                } else if (c->delivery_system == SYS_DVBT2) {
1200                        mutex_lock(priv->spi_mutex);
1201                        ret = cxd2880_post_bit_err_t2(&priv->tnrdmd,
1202                                                      &post_bit_err,
1203                                                      &post_bit_count);
1204                        mutex_unlock(priv->spi_mutex);
1205                } else {
1206                        return -EINVAL;
1207                }
1208
1209                if (!ret) {
1210                        c->post_bit_error.len = 1;
1211                        c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
1212                        c->post_bit_error.stat[0].uvalue += post_bit_err;
1213                        c->post_bit_count.len = 1;
1214                        c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
1215                        c->post_bit_count.stat[0].uvalue += post_bit_count;
1216                } else {
1217                        c->post_bit_error.len = 1;
1218                        c->post_bit_error.stat[0].scale =
1219                                                        FE_SCALE_NOT_AVAILABLE;
1220                        c->post_bit_count.len = 1;
1221                        c->post_bit_count.stat[0].scale =
1222                                                        FE_SCALE_NOT_AVAILABLE;
1223                        pr_debug("post_bit_err_t %d\n", ret);
1224                }
1225        }
1226
1227        if (time_after(jiffies, priv->ucblock_update)) {
1228                priv->ucblock_update =
1229                        jiffies + msecs_to_jiffies(priv->ucblock_interval);
1230                if (c->delivery_system == SYS_DVBT) {
1231                        mutex_lock(priv->spi_mutex);
1232                        ret = cxd2880_read_block_err_t(&priv->tnrdmd,
1233                                                       &block_err,
1234                                                       &block_count);
1235                        mutex_unlock(priv->spi_mutex);
1236                } else if (c->delivery_system == SYS_DVBT2) {
1237                        mutex_lock(priv->spi_mutex);
1238                        ret = cxd2880_read_block_err_t2(&priv->tnrdmd,
1239                                                        &block_err,
1240                                                        &block_count);
1241                        mutex_unlock(priv->spi_mutex);
1242                } else {
1243                        return -EINVAL;
1244                }
1245                if (!ret) {
1246                        c->block_error.len = 1;
1247                        c->block_error.stat[0].scale = FE_SCALE_COUNTER;
1248                        c->block_error.stat[0].uvalue += block_err;
1249                        c->block_count.len = 1;
1250                        c->block_count.stat[0].scale = FE_SCALE_COUNTER;
1251                        c->block_count.stat[0].uvalue += block_count;
1252                } else {
1253                        c->block_error.len = 1;
1254                        c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1255                        c->block_count.len = 1;
1256                        c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1257                        pr_debug("read_block_err_t  %d\n", ret);
1258                }
1259        }
1260
1261        return 0;
1262}
1263
1264static int cxd2880_check_l1post_plp(struct dvb_frontend *fe)
1265{
1266        u8 valid = 0;
1267        u8 plp_not_found;
1268        int ret;
1269        struct cxd2880_priv *priv = NULL;
1270
1271        if (!fe) {
1272                pr_err("invalid arg\n");
1273                return -EINVAL;
1274        }
1275
1276        priv = fe->demodulator_priv;
1277
1278        ret = cxd2880_tnrdmd_dvbt2_check_l1post_valid(&priv->tnrdmd,
1279                                                      &valid);
1280        if (ret)
1281                return ret;
1282
1283        if (!valid)
1284                return -EAGAIN;
1285
1286        ret = cxd2880_tnrdmd_dvbt2_mon_data_plp_error(&priv->tnrdmd,
1287                                                      &plp_not_found);
1288        if (ret)
1289                return ret;
1290
1291        if (plp_not_found) {
1292                priv->dvbt2_tune_param.tune_info =
1293                        CXD2880_TNRDMD_DVBT2_TUNE_INFO_INVALID_PLP_ID;
1294        } else {
1295                priv->dvbt2_tune_param.tune_info =
1296                        CXD2880_TNRDMD_DVBT2_TUNE_INFO_OK;
1297        }
1298
1299        return 0;
1300}
1301
1302static int cxd2880_read_status(struct dvb_frontend *fe,
1303                               enum fe_status *status)
1304{
1305        int ret;
1306        u8 sync = 0;
1307        u8 lock = 0;
1308        u8 unlock = 0;
1309        struct cxd2880_priv *priv = NULL;
1310        struct dtv_frontend_properties *c = NULL;
1311
1312        if (!fe || !status) {
1313                pr_err("invalid arg\n");
1314                return -EINVAL;
1315        }
1316
1317        priv = fe->demodulator_priv;
1318        c = &fe->dtv_property_cache;
1319        *status = 0;
1320
1321        if (priv->tnrdmd.state == CXD2880_TNRDMD_STATE_ACTIVE) {
1322                mutex_lock(priv->spi_mutex);
1323                if (c->delivery_system == SYS_DVBT) {
1324                        ret = cxd2880_tnrdmd_dvbt_mon_sync_stat(&priv->tnrdmd,
1325                                                                &sync,
1326                                                                &lock,
1327                                                                &unlock);
1328                } else if (c->delivery_system == SYS_DVBT2) {
1329                        ret = cxd2880_tnrdmd_dvbt2_mon_sync_stat(&priv->tnrdmd,
1330                                                                 &sync,
1331                                                                 &lock,
1332                                                                 &unlock);
1333                } else {
1334                        pr_err("invalid system");
1335                        mutex_unlock(priv->spi_mutex);
1336                        return -EINVAL;
1337                }
1338
1339                mutex_unlock(priv->spi_mutex);
1340                if (ret) {
1341                        pr_err("failed. sys = %d\n", priv->tnrdmd.sys);
1342                        return  ret;
1343                }
1344
1345                if (sync == 6) {
1346                        *status = FE_HAS_SIGNAL |
1347                                  FE_HAS_CARRIER;
1348                }
1349                if (lock)
1350                        *status |= FE_HAS_VITERBI |
1351                                   FE_HAS_SYNC |
1352                                   FE_HAS_LOCK;
1353        }
1354
1355        pr_debug("status %d\n", *status);
1356
1357        if (priv->s == 0 && (*status & FE_HAS_LOCK) &&
1358            (*status & FE_HAS_CARRIER)) {
1359                mutex_lock(priv->spi_mutex);
1360                if (c->delivery_system == SYS_DVBT) {
1361                        ret = cxd2880_set_ber_per_period_t(fe);
1362                        priv->s = *status;
1363                } else if (c->delivery_system == SYS_DVBT2) {
1364                        ret = cxd2880_check_l1post_plp(fe);
1365                        if (!ret) {
1366                                ret = cxd2880_set_ber_per_period_t2(fe);
1367                                priv->s = *status;
1368                        }
1369                } else {
1370                        pr_err("invalid system\n");
1371                        mutex_unlock(priv->spi_mutex);
1372                        return -EINVAL;
1373                }
1374                mutex_unlock(priv->spi_mutex);
1375        }
1376
1377        cxd2880_get_stats(fe, *status);
1378        return  0;
1379}
1380
1381static int cxd2880_tune(struct dvb_frontend *fe,
1382                        bool retune,
1383                        unsigned int mode_flags,
1384                        unsigned int *delay,
1385                        enum fe_status *status)
1386{
1387        int ret;
1388
1389        if (!fe || !delay || !status) {
1390                pr_err("invalid arg.");
1391                return -EINVAL;
1392        }
1393
1394        if (retune) {
1395                ret = cxd2880_set_frontend(fe);
1396                if (ret) {
1397                        pr_err("cxd2880_set_frontend failed %d\n", ret);
1398                        return ret;
1399                }
1400        }
1401
1402        *delay = HZ / 5;
1403
1404        return cxd2880_read_status(fe, status);
1405}
1406
1407static int cxd2880_get_frontend_t(struct dvb_frontend *fe,
1408                                  struct dtv_frontend_properties *c)
1409{
1410        int ret;
1411        struct cxd2880_priv *priv = NULL;
1412        enum cxd2880_dvbt_mode mode = CXD2880_DVBT_MODE_2K;
1413        enum cxd2880_dvbt_guard guard = CXD2880_DVBT_GUARD_1_32;
1414        struct cxd2880_dvbt_tpsinfo tps;
1415        enum cxd2880_tnrdmd_spectrum_sense sense;
1416        u16 snr = 0;
1417        int strength = 0;
1418
1419        if (!fe || !c) {
1420                pr_err("invalid arg\n");
1421                return -EINVAL;
1422        }
1423
1424        priv = fe->demodulator_priv;
1425
1426        mutex_lock(priv->spi_mutex);
1427        ret = cxd2880_tnrdmd_dvbt_mon_mode_guard(&priv->tnrdmd,
1428                                                 &mode, &guard);
1429        mutex_unlock(priv->spi_mutex);
1430        if (!ret) {
1431                switch (mode) {
1432                case CXD2880_DVBT_MODE_2K:
1433                        c->transmission_mode = TRANSMISSION_MODE_2K;
1434                        break;
1435                case CXD2880_DVBT_MODE_8K:
1436                        c->transmission_mode = TRANSMISSION_MODE_8K;
1437                        break;
1438                default:
1439                        c->transmission_mode = TRANSMISSION_MODE_2K;
1440                        pr_debug("transmission mode is invalid %d\n", mode);
1441                        break;
1442                }
1443                switch (guard) {
1444                case CXD2880_DVBT_GUARD_1_32:
1445                        c->guard_interval = GUARD_INTERVAL_1_32;
1446                        break;
1447                case CXD2880_DVBT_GUARD_1_16:
1448                        c->guard_interval = GUARD_INTERVAL_1_16;
1449                        break;
1450                case CXD2880_DVBT_GUARD_1_8:
1451                        c->guard_interval = GUARD_INTERVAL_1_8;
1452                        break;
1453                case CXD2880_DVBT_GUARD_1_4:
1454                        c->guard_interval = GUARD_INTERVAL_1_4;
1455                        break;
1456                default:
1457                        c->guard_interval = GUARD_INTERVAL_1_32;
1458                        pr_debug("guard interval is invalid %d\n",
1459                                 guard);
1460                        break;
1461                }
1462        } else {
1463                c->transmission_mode = TRANSMISSION_MODE_2K;
1464                c->guard_interval = GUARD_INTERVAL_1_32;
1465                pr_debug("ModeGuard err %d\n", ret);
1466        }
1467
1468        mutex_lock(priv->spi_mutex);
1469        ret = cxd2880_tnrdmd_dvbt_mon_tps_info(&priv->tnrdmd, &tps);
1470        mutex_unlock(priv->spi_mutex);
1471        if (!ret) {
1472                switch (tps.hierarchy) {
1473                case CXD2880_DVBT_HIERARCHY_NON:
1474                        c->hierarchy = HIERARCHY_NONE;
1475                        break;
1476                case CXD2880_DVBT_HIERARCHY_1:
1477                        c->hierarchy = HIERARCHY_1;
1478                        break;
1479                case CXD2880_DVBT_HIERARCHY_2:
1480                        c->hierarchy = HIERARCHY_2;
1481                        break;
1482                case CXD2880_DVBT_HIERARCHY_4:
1483                        c->hierarchy = HIERARCHY_4;
1484                        break;
1485                default:
1486                        c->hierarchy = HIERARCHY_NONE;
1487                        pr_debug("TPSInfo hierarchy is invalid %d\n",
1488                                 tps.hierarchy);
1489                        break;
1490                }
1491
1492                switch (tps.rate_hp) {
1493                case CXD2880_DVBT_CODERATE_1_2:
1494                        c->code_rate_HP = FEC_1_2;
1495                        break;
1496                case CXD2880_DVBT_CODERATE_2_3:
1497                        c->code_rate_HP = FEC_2_3;
1498                        break;
1499                case CXD2880_DVBT_CODERATE_3_4:
1500                        c->code_rate_HP = FEC_3_4;
1501                        break;
1502                case CXD2880_DVBT_CODERATE_5_6:
1503                        c->code_rate_HP = FEC_5_6;
1504                        break;
1505                case CXD2880_DVBT_CODERATE_7_8:
1506                        c->code_rate_HP = FEC_7_8;
1507                        break;
1508                default:
1509                        c->code_rate_HP = FEC_NONE;
1510                        pr_debug("TPSInfo rateHP is invalid %d\n",
1511                                 tps.rate_hp);
1512                        break;
1513                }
1514                switch (tps.rate_lp) {
1515                case CXD2880_DVBT_CODERATE_1_2:
1516                        c->code_rate_LP = FEC_1_2;
1517                        break;
1518                case CXD2880_DVBT_CODERATE_2_3:
1519                        c->code_rate_LP = FEC_2_3;
1520                        break;
1521                case CXD2880_DVBT_CODERATE_3_4:
1522                        c->code_rate_LP = FEC_3_4;
1523                        break;
1524                case CXD2880_DVBT_CODERATE_5_6:
1525                        c->code_rate_LP = FEC_5_6;
1526                        break;
1527                case CXD2880_DVBT_CODERATE_7_8:
1528                        c->code_rate_LP = FEC_7_8;
1529                        break;
1530                default:
1531                        c->code_rate_LP = FEC_NONE;
1532                        pr_debug("TPSInfo rateLP is invalid %d\n",
1533                                 tps.rate_lp);
1534                        break;
1535                }
1536                switch (tps.constellation) {
1537                case CXD2880_DVBT_CONSTELLATION_QPSK:
1538                        c->modulation = QPSK;
1539                        break;
1540                case CXD2880_DVBT_CONSTELLATION_16QAM:
1541                        c->modulation = QAM_16;
1542                        break;
1543                case CXD2880_DVBT_CONSTELLATION_64QAM:
1544                        c->modulation = QAM_64;
1545                        break;
1546                default:
1547                        c->modulation = QPSK;
1548                        pr_debug("TPSInfo constellation is invalid %d\n",
1549                                 tps.constellation);
1550                        break;
1551                }
1552        } else {
1553                c->hierarchy = HIERARCHY_NONE;
1554                c->code_rate_HP = FEC_NONE;
1555                c->code_rate_LP = FEC_NONE;
1556                c->modulation = QPSK;
1557                pr_debug("TPS info err %d\n", ret);
1558        }
1559
1560        mutex_lock(priv->spi_mutex);
1561        ret = cxd2880_tnrdmd_dvbt_mon_spectrum_sense(&priv->tnrdmd, &sense);
1562        mutex_unlock(priv->spi_mutex);
1563        if (!ret) {
1564                switch (sense) {
1565                case CXD2880_TNRDMD_SPECTRUM_NORMAL:
1566                        c->inversion = INVERSION_OFF;
1567                        break;
1568                case CXD2880_TNRDMD_SPECTRUM_INV:
1569                        c->inversion = INVERSION_ON;
1570                        break;
1571                default:
1572                        c->inversion = INVERSION_OFF;
1573                        pr_debug("spectrum sense is invalid %d\n", sense);
1574                        break;
1575                }
1576        } else {
1577                c->inversion = INVERSION_OFF;
1578                pr_debug("spectrum_sense %d\n", ret);
1579        }
1580
1581        mutex_lock(priv->spi_mutex);
1582        ret = cxd2880_tnrdmd_mon_rf_lvl(&priv->tnrdmd, &strength);
1583        mutex_unlock(priv->spi_mutex);
1584        if (!ret) {
1585                c->strength.len = 1;
1586                c->strength.stat[0].scale = FE_SCALE_DECIBEL;
1587                c->strength.stat[0].svalue = strength;
1588        } else {
1589                c->strength.len = 1;
1590                c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1591                pr_debug("mon_rf_lvl %d\n", ret);
1592        }
1593
1594        ret = cxd2880_read_snr(fe, &snr);
1595        if (!ret) {
1596                c->cnr.len = 1;
1597                c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
1598                c->cnr.stat[0].svalue = snr;
1599        } else {
1600                c->cnr.len = 1;
1601                c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1602                pr_debug("read_snr %d\n", ret);
1603        }
1604
1605        return 0;
1606}
1607
1608static int cxd2880_get_frontend_t2(struct dvb_frontend *fe,
1609                                   struct dtv_frontend_properties *c)
1610{
1611        int ret;
1612        struct cxd2880_priv *priv = NULL;
1613        struct cxd2880_dvbt2_l1pre l1pre;
1614        enum cxd2880_dvbt2_plp_code_rate coderate;
1615        enum cxd2880_dvbt2_plp_constell qam;
1616        enum cxd2880_tnrdmd_spectrum_sense sense;
1617        u16 snr = 0;
1618        int strength = 0;
1619
1620        if (!fe || !c) {
1621                pr_err("invalid arg.\n");
1622                return -EINVAL;
1623        }
1624
1625        priv = fe->demodulator_priv;
1626
1627        mutex_lock(priv->spi_mutex);
1628        ret = cxd2880_tnrdmd_dvbt2_mon_l1_pre(&priv->tnrdmd, &l1pre);
1629        mutex_unlock(priv->spi_mutex);
1630        if (!ret) {
1631                switch (l1pre.fft_mode) {
1632                case CXD2880_DVBT2_M2K:
1633                        c->transmission_mode = TRANSMISSION_MODE_2K;
1634                        break;
1635                case CXD2880_DVBT2_M8K:
1636                        c->transmission_mode = TRANSMISSION_MODE_8K;
1637                        break;
1638                case CXD2880_DVBT2_M4K:
1639                        c->transmission_mode = TRANSMISSION_MODE_4K;
1640                        break;
1641                case CXD2880_DVBT2_M1K:
1642                        c->transmission_mode = TRANSMISSION_MODE_1K;
1643                        break;
1644                case CXD2880_DVBT2_M16K:
1645                        c->transmission_mode = TRANSMISSION_MODE_16K;
1646                        break;
1647                case CXD2880_DVBT2_M32K:
1648                        c->transmission_mode = TRANSMISSION_MODE_32K;
1649                        break;
1650                default:
1651                        c->transmission_mode = TRANSMISSION_MODE_2K;
1652                        pr_debug("L1Pre fft_mode is invalid %d\n",
1653                                 l1pre.fft_mode);
1654                        break;
1655                }
1656                switch (l1pre.gi) {
1657                case CXD2880_DVBT2_G1_32:
1658                        c->guard_interval = GUARD_INTERVAL_1_32;
1659                        break;
1660                case CXD2880_DVBT2_G1_16:
1661                        c->guard_interval = GUARD_INTERVAL_1_16;
1662                        break;
1663                case CXD2880_DVBT2_G1_8:
1664                        c->guard_interval = GUARD_INTERVAL_1_8;
1665                        break;
1666                case CXD2880_DVBT2_G1_4:
1667                        c->guard_interval = GUARD_INTERVAL_1_4;
1668                        break;
1669                case CXD2880_DVBT2_G1_128:
1670                        c->guard_interval = GUARD_INTERVAL_1_128;
1671                        break;
1672                case CXD2880_DVBT2_G19_128:
1673                        c->guard_interval = GUARD_INTERVAL_19_128;
1674                        break;
1675                case CXD2880_DVBT2_G19_256:
1676                        c->guard_interval = GUARD_INTERVAL_19_256;
1677                        break;
1678                default:
1679                        c->guard_interval = GUARD_INTERVAL_1_32;
1680                        pr_debug("L1Pre guard interval is invalid %d\n",
1681                                 l1pre.gi);
1682                        break;
1683                }
1684        } else {
1685                c->transmission_mode = TRANSMISSION_MODE_2K;
1686                c->guard_interval = GUARD_INTERVAL_1_32;
1687                pr_debug("L1Pre err %d\n", ret);
1688        }
1689
1690        mutex_lock(priv->spi_mutex);
1691        ret = cxd2880_tnrdmd_dvbt2_mon_code_rate(&priv->tnrdmd,
1692                                                 CXD2880_DVBT2_PLP_DATA,
1693                                                 &coderate);
1694        mutex_unlock(priv->spi_mutex);
1695        if (!ret) {
1696                switch (coderate) {
1697                case CXD2880_DVBT2_R1_2:
1698                        c->fec_inner = FEC_1_2;
1699                        break;
1700                case CXD2880_DVBT2_R3_5:
1701                        c->fec_inner = FEC_3_5;
1702                        break;
1703                case CXD2880_DVBT2_R2_3:
1704                        c->fec_inner = FEC_2_3;
1705                        break;
1706                case CXD2880_DVBT2_R3_4:
1707                        c->fec_inner = FEC_3_4;
1708                        break;
1709                case CXD2880_DVBT2_R4_5:
1710                        c->fec_inner = FEC_4_5;
1711                        break;
1712                case CXD2880_DVBT2_R5_6:
1713                        c->fec_inner = FEC_5_6;
1714                        break;
1715                default:
1716                        c->fec_inner = FEC_NONE;
1717                        pr_debug("CodeRate is invalid %d\n", coderate);
1718                        break;
1719                }
1720        } else {
1721                c->fec_inner = FEC_NONE;
1722                pr_debug("CodeRate %d\n", ret);
1723        }
1724
1725        mutex_lock(priv->spi_mutex);
1726        ret = cxd2880_tnrdmd_dvbt2_mon_qam(&priv->tnrdmd,
1727                                           CXD2880_DVBT2_PLP_DATA,
1728                                           &qam);
1729        mutex_unlock(priv->spi_mutex);
1730        if (!ret) {
1731                switch (qam) {
1732                case CXD2880_DVBT2_QPSK:
1733                        c->modulation = QPSK;
1734                        break;
1735                case CXD2880_DVBT2_QAM16:
1736                        c->modulation = QAM_16;
1737                        break;
1738                case CXD2880_DVBT2_QAM64:
1739                        c->modulation = QAM_64;
1740                        break;
1741                case CXD2880_DVBT2_QAM256:
1742                        c->modulation = QAM_256;
1743                        break;
1744                default:
1745                        c->modulation = QPSK;
1746                        pr_debug("QAM is invalid %d\n", qam);
1747                        break;
1748                }
1749        } else {
1750                c->modulation = QPSK;
1751                pr_debug("QAM %d\n", ret);
1752        }
1753
1754        mutex_lock(priv->spi_mutex);
1755        ret = cxd2880_tnrdmd_dvbt2_mon_spectrum_sense(&priv->tnrdmd, &sense);
1756        mutex_unlock(priv->spi_mutex);
1757        if (!ret) {
1758                switch (sense) {
1759                case CXD2880_TNRDMD_SPECTRUM_NORMAL:
1760                        c->inversion = INVERSION_OFF;
1761                        break;
1762                case CXD2880_TNRDMD_SPECTRUM_INV:
1763                        c->inversion = INVERSION_ON;
1764                        break;
1765                default:
1766                        c->inversion = INVERSION_OFF;
1767                        pr_debug("spectrum sense is invalid %d\n", sense);
1768                        break;
1769                }
1770        } else {
1771                c->inversion = INVERSION_OFF;
1772                pr_debug("SpectrumSense %d\n", ret);
1773        }
1774
1775        mutex_lock(priv->spi_mutex);
1776        ret = cxd2880_tnrdmd_mon_rf_lvl(&priv->tnrdmd, &strength);
1777        mutex_unlock(priv->spi_mutex);
1778        if (!ret) {
1779                c->strength.len = 1;
1780                c->strength.stat[0].scale = FE_SCALE_DECIBEL;
1781                c->strength.stat[0].svalue = strength;
1782        } else {
1783                c->strength.len = 1;
1784                c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1785                pr_debug("mon_rf_lvl %d\n", ret);
1786        }
1787
1788        ret = cxd2880_read_snr(fe, &snr);
1789        if (!ret) {
1790                c->cnr.len = 1;
1791                c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
1792                c->cnr.stat[0].svalue = snr;
1793        } else {
1794                c->cnr.len = 1;
1795                c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1796                pr_debug("read_snr %d\n", ret);
1797        }
1798
1799        return 0;
1800}
1801
1802static int cxd2880_get_frontend(struct dvb_frontend *fe,
1803                                struct dtv_frontend_properties *props)
1804{
1805        int ret;
1806
1807        if (!fe || !props) {
1808                pr_err("invalid arg.");
1809                return -EINVAL;
1810        }
1811
1812        pr_debug("system=%d\n", fe->dtv_property_cache.delivery_system);
1813        switch (fe->dtv_property_cache.delivery_system) {
1814        case SYS_DVBT:
1815                ret = cxd2880_get_frontend_t(fe, props);
1816                break;
1817        case SYS_DVBT2:
1818                ret = cxd2880_get_frontend_t2(fe, props);
1819                break;
1820        default:
1821                ret = -EINVAL;
1822                break;
1823        }
1824
1825        return ret;
1826}
1827
1828static enum dvbfe_algo cxd2880_get_frontend_algo(struct dvb_frontend *fe)
1829{
1830        return DVBFE_ALGO_HW;
1831}
1832
1833static struct dvb_frontend_ops cxd2880_dvbt_t2_ops = {
1834        .info = {
1835                .name = "Sony CXD2880",
1836                .frequency_min_hz = 174 * MHz,
1837                .frequency_max_hz = 862 * MHz,
1838                .frequency_stepsize_hz = 1 * kHz,
1839                .caps = FE_CAN_INVERSION_AUTO |
1840                                FE_CAN_FEC_1_2 |
1841                                FE_CAN_FEC_2_3 |
1842                                FE_CAN_FEC_3_4 |
1843                                FE_CAN_FEC_4_5 |
1844                                FE_CAN_FEC_5_6  |
1845                                FE_CAN_FEC_7_8  |
1846                                FE_CAN_FEC_AUTO |
1847                                FE_CAN_QPSK |
1848                                FE_CAN_QAM_16 |
1849                                FE_CAN_QAM_32 |
1850                                FE_CAN_QAM_64 |
1851                                FE_CAN_QAM_128 |
1852                                FE_CAN_QAM_256 |
1853                                FE_CAN_QAM_AUTO |
1854                                FE_CAN_TRANSMISSION_MODE_AUTO |
1855                                FE_CAN_GUARD_INTERVAL_AUTO |
1856                                FE_CAN_2G_MODULATION |
1857                                FE_CAN_RECOVER |
1858                                FE_CAN_MUTE_TS,
1859        },
1860        .delsys = { SYS_DVBT, SYS_DVBT2 },
1861
1862        .release = cxd2880_release,
1863        .init = cxd2880_init,
1864        .sleep = cxd2880_sleep,
1865        .tune = cxd2880_tune,
1866        .set_frontend = cxd2880_set_frontend,
1867        .get_frontend = cxd2880_get_frontend,
1868        .read_status = cxd2880_read_status,
1869        .read_ber = cxd2880_read_ber,
1870        .read_signal_strength = cxd2880_read_signal_strength,
1871        .read_snr = cxd2880_read_snr,
1872        .read_ucblocks = cxd2880_read_ucblocks,
1873        .get_frontend_algo = cxd2880_get_frontend_algo,
1874};
1875
1876struct dvb_frontend *cxd2880_attach(struct dvb_frontend *fe,
1877                                    struct cxd2880_config *cfg)
1878{
1879        int ret;
1880        enum cxd2880_tnrdmd_chip_id chipid =
1881                                        CXD2880_TNRDMD_CHIP_ID_UNKNOWN;
1882        static struct cxd2880_priv *priv;
1883        u8 data = 0;
1884
1885        if (!fe) {
1886                pr_err("invalid arg.\n");
1887                return NULL;
1888        }
1889
1890        priv = kzalloc(sizeof(struct cxd2880_priv), GFP_KERNEL);
1891        if (!priv)
1892                return NULL;
1893
1894        priv->spi = cfg->spi;
1895        priv->spi_mutex = cfg->spi_mutex;
1896        priv->spi_device.spi = cfg->spi;
1897
1898        memcpy(&fe->ops, &cxd2880_dvbt_t2_ops,
1899               sizeof(struct dvb_frontend_ops));
1900
1901        ret = cxd2880_spi_device_initialize(&priv->spi_device,
1902                                            CXD2880_SPI_MODE_0,
1903                                            55000000);
1904        if (ret) {
1905                pr_err("spi_device_initialize failed. %d\n", ret);
1906                kfree(priv);
1907                return NULL;
1908        }
1909
1910        ret = cxd2880_spi_device_create_spi(&priv->cxd2880_spi,
1911                                            &priv->spi_device);
1912        if (ret) {
1913                pr_err("spi_device_create_spi failed. %d\n", ret);
1914                kfree(priv);
1915                return NULL;
1916        }
1917
1918        ret = cxd2880_io_spi_create(&priv->regio, &priv->cxd2880_spi, 0);
1919        if (ret) {
1920                pr_err("io_spi_create failed. %d\n", ret);
1921                kfree(priv);
1922                return NULL;
1923        }
1924        ret = priv->regio.write_reg(&priv->regio,
1925                                    CXD2880_IO_TGT_SYS, 0x00, 0x00);
1926        if (ret) {
1927                pr_err("set bank to 0x00 failed.\n");
1928                kfree(priv);
1929                return NULL;
1930        }
1931        ret = priv->regio.read_regs(&priv->regio,
1932                                    CXD2880_IO_TGT_SYS, 0xfd, &data, 1);
1933        if (ret) {
1934                pr_err("read chip id failed.\n");
1935                kfree(priv);
1936                return NULL;
1937        }
1938
1939        chipid = (enum cxd2880_tnrdmd_chip_id)data;
1940        if (chipid != CXD2880_TNRDMD_CHIP_ID_CXD2880_ES1_0X &&
1941            chipid != CXD2880_TNRDMD_CHIP_ID_CXD2880_ES1_11) {
1942                pr_err("chip id invalid.\n");
1943                kfree(priv);
1944                return NULL;
1945        }
1946
1947        fe->demodulator_priv = priv;
1948        pr_info("CXD2880 driver version: Ver %s\n",
1949                CXD2880_TNRDMD_DRIVER_VERSION);
1950
1951        return fe;
1952}
1953EXPORT_SYMBOL(cxd2880_attach);
1954
1955MODULE_DESCRIPTION("Sony CXD2880 DVB-T2/T tuner + demod driver");
1956MODULE_AUTHOR("Sony Semiconductor Solutions Corporation");
1957MODULE_LICENSE("GPL v2");
1958