Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * cxd2880_top.c
0004  * Sony CXD2880 DVB-T2/T tuner + demodulator driver
0005  *
0006  * Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
0007  */
0008 
0009 #define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
0010 
0011 #include <linux/spi/spi.h>
0012 
0013 #include <media/dvb_frontend.h>
0014 #include <media/dvb_math.h>
0015 
0016 #include "cxd2880.h"
0017 #include "cxd2880_tnrdmd_mon.h"
0018 #include "cxd2880_tnrdmd_dvbt2_mon.h"
0019 #include "cxd2880_tnrdmd_dvbt_mon.h"
0020 #include "cxd2880_integ.h"
0021 #include "cxd2880_tnrdmd_dvbt2.h"
0022 #include "cxd2880_tnrdmd_dvbt.h"
0023 #include "cxd2880_devio_spi.h"
0024 #include "cxd2880_spi_device.h"
0025 #include "cxd2880_tnrdmd_driver_version.h"
0026 
0027 struct cxd2880_priv {
0028     struct cxd2880_tnrdmd tnrdmd;
0029     struct spi_device *spi;
0030     struct cxd2880_io regio;
0031     struct cxd2880_spi_device spi_device;
0032     struct cxd2880_spi cxd2880_spi;
0033     struct cxd2880_dvbt_tune_param dvbt_tune_param;
0034     struct cxd2880_dvbt2_tune_param dvbt2_tune_param;
0035     struct mutex *spi_mutex; /* For SPI access exclusive control */
0036     unsigned long pre_ber_update;
0037     unsigned long pre_ber_interval;
0038     unsigned long post_ber_update;
0039     unsigned long post_ber_interval;
0040     unsigned long ucblock_update;
0041     unsigned long ucblock_interval;
0042     enum fe_status s;
0043 };
0044 
0045 static int cxd2880_pre_bit_err_t(struct cxd2880_tnrdmd *tnrdmd,
0046                  u32 *pre_bit_err, u32 *pre_bit_count)
0047 {
0048     u8 rdata[2];
0049     int ret;
0050 
0051     if (!tnrdmd || !pre_bit_err || !pre_bit_count)
0052         return -EINVAL;
0053 
0054     if (tnrdmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
0055         return -EINVAL;
0056 
0057     if (tnrdmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
0058         return -EINVAL;
0059 
0060     if (tnrdmd->sys != CXD2880_DTV_SYS_DVBT)
0061         return -EINVAL;
0062 
0063     ret = slvt_freeze_reg(tnrdmd);
0064     if (ret)
0065         return ret;
0066 
0067     ret = tnrdmd->io->write_reg(tnrdmd->io,
0068                     CXD2880_IO_TGT_DMD,
0069                     0x00, 0x10);
0070     if (ret) {
0071         slvt_unfreeze_reg(tnrdmd);
0072         return ret;
0073     }
0074 
0075     ret = tnrdmd->io->read_regs(tnrdmd->io,
0076                     CXD2880_IO_TGT_DMD,
0077                     0x39, rdata, 1);
0078     if (ret) {
0079         slvt_unfreeze_reg(tnrdmd);
0080         return ret;
0081     }
0082 
0083     if ((rdata[0] & 0x01) == 0) {
0084         slvt_unfreeze_reg(tnrdmd);
0085         return -EAGAIN;
0086     }
0087 
0088     ret = tnrdmd->io->read_regs(tnrdmd->io,
0089                     CXD2880_IO_TGT_DMD,
0090                     0x22, rdata, 2);
0091     if (ret) {
0092         slvt_unfreeze_reg(tnrdmd);
0093         return ret;
0094     }
0095 
0096     *pre_bit_err = (rdata[0] << 8) | rdata[1];
0097 
0098     ret = tnrdmd->io->read_regs(tnrdmd->io,
0099                     CXD2880_IO_TGT_DMD,
0100                     0x6f, rdata, 1);
0101     if (ret) {
0102         slvt_unfreeze_reg(tnrdmd);
0103         return ret;
0104     }
0105 
0106     slvt_unfreeze_reg(tnrdmd);
0107 
0108     *pre_bit_count = ((rdata[0] & 0x07) == 0) ?
0109              256 : (0x1000 << (rdata[0] & 0x07));
0110 
0111     return 0;
0112 }
0113 
0114 static int cxd2880_pre_bit_err_t2(struct cxd2880_tnrdmd *tnrdmd,
0115                   u32 *pre_bit_err,
0116                   u32 *pre_bit_count)
0117 {
0118     u32 period_exp = 0;
0119     u32 n_ldpc = 0;
0120     u8 data[5];
0121     int ret;
0122 
0123     if (!tnrdmd || !pre_bit_err || !pre_bit_count)
0124         return -EINVAL;
0125 
0126     if (tnrdmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
0127         return -EINVAL;
0128 
0129     if (tnrdmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
0130         return -EINVAL;
0131 
0132     if (tnrdmd->sys != CXD2880_DTV_SYS_DVBT2)
0133         return -EINVAL;
0134 
0135     ret = slvt_freeze_reg(tnrdmd);
0136     if (ret)
0137         return ret;
0138 
0139     ret = tnrdmd->io->write_reg(tnrdmd->io,
0140                     CXD2880_IO_TGT_DMD,
0141                     0x00, 0x0b);
0142     if (ret) {
0143         slvt_unfreeze_reg(tnrdmd);
0144         return ret;
0145     }
0146 
0147     ret = tnrdmd->io->read_regs(tnrdmd->io,
0148                     CXD2880_IO_TGT_DMD,
0149                     0x3c, data, sizeof(data));
0150     if (ret) {
0151         slvt_unfreeze_reg(tnrdmd);
0152         return ret;
0153     }
0154 
0155     if (!(data[0] & 0x01)) {
0156         slvt_unfreeze_reg(tnrdmd);
0157         return -EAGAIN;
0158     }
0159     *pre_bit_err =
0160     ((data[1] & 0x0f) << 24) | (data[2] << 16) | (data[3] << 8) | data[4];
0161 
0162     ret = tnrdmd->io->read_regs(tnrdmd->io,
0163                     CXD2880_IO_TGT_DMD,
0164                     0xa0, data, 1);
0165     if (ret) {
0166         slvt_unfreeze_reg(tnrdmd);
0167         return ret;
0168     }
0169 
0170     if (((enum cxd2880_dvbt2_plp_fec)(data[0] & 0x03)) ==
0171         CXD2880_DVBT2_FEC_LDPC_16K)
0172         n_ldpc = 16200;
0173     else
0174         n_ldpc = 64800;
0175     slvt_unfreeze_reg(tnrdmd);
0176 
0177     ret = tnrdmd->io->write_reg(tnrdmd->io,
0178                     CXD2880_IO_TGT_DMD,
0179                     0x00, 0x20);
0180     if (ret)
0181         return ret;
0182 
0183     ret = tnrdmd->io->read_regs(tnrdmd->io,
0184                     CXD2880_IO_TGT_DMD,
0185                     0x6f, data, 1);
0186     if (ret)
0187         return ret;
0188 
0189     period_exp = data[0] & 0x0f;
0190 
0191     *pre_bit_count = (1U << period_exp) * n_ldpc;
0192 
0193     return 0;
0194 }
0195 
0196 static int cxd2880_post_bit_err_t(struct cxd2880_tnrdmd *tnrdmd,
0197                   u32 *post_bit_err,
0198                   u32 *post_bit_count)
0199 {
0200     u8 rdata[3];
0201     u32 bit_error = 0;
0202     u32 period_exp = 0;
0203     int ret;
0204 
0205     if (!tnrdmd || !post_bit_err || !post_bit_count)
0206         return -EINVAL;
0207 
0208     if (tnrdmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
0209         return -EINVAL;
0210 
0211     if (tnrdmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
0212         return -EINVAL;
0213 
0214     if (tnrdmd->sys != CXD2880_DTV_SYS_DVBT)
0215         return -EINVAL;
0216 
0217     ret = tnrdmd->io->write_reg(tnrdmd->io,
0218                     CXD2880_IO_TGT_DMD,
0219                     0x00, 0x0d);
0220     if (ret)
0221         return ret;
0222 
0223     ret = tnrdmd->io->read_regs(tnrdmd->io,
0224                     CXD2880_IO_TGT_DMD,
0225                     0x15, rdata, 3);
0226     if (ret)
0227         return ret;
0228 
0229     if ((rdata[0] & 0x40) == 0)
0230         return -EAGAIN;
0231 
0232     *post_bit_err = ((rdata[0] & 0x3f) << 16) | (rdata[1] << 8) | rdata[2];
0233 
0234     ret = tnrdmd->io->write_reg(tnrdmd->io,
0235                     CXD2880_IO_TGT_DMD,
0236                     0x00, 0x10);
0237     if (ret)
0238         return ret;
0239 
0240     ret = tnrdmd->io->read_regs(tnrdmd->io,
0241                     CXD2880_IO_TGT_DMD,
0242                     0x60, rdata, 1);
0243     if (ret)
0244         return ret;
0245 
0246     period_exp = (rdata[0] & 0x1f);
0247 
0248     if (period_exp <= 11 && (bit_error > (1U << period_exp) * 204 * 8))
0249         return -EAGAIN;
0250 
0251     *post_bit_count = (1U << period_exp) * 204 * 8;
0252 
0253     return 0;
0254 }
0255 
0256 static int cxd2880_post_bit_err_t2(struct cxd2880_tnrdmd *tnrdmd,
0257                    u32 *post_bit_err,
0258                    u32 *post_bit_count)
0259 {
0260     u32 period_exp = 0;
0261     u32 n_bch = 0;
0262     u8 data[3];
0263     enum cxd2880_dvbt2_plp_fec plp_fec_type =
0264         CXD2880_DVBT2_FEC_LDPC_16K;
0265     enum cxd2880_dvbt2_plp_code_rate plp_code_rate =
0266         CXD2880_DVBT2_R1_2;
0267     int ret;
0268     static const u16 n_bch_bits_lookup[2][8] = {
0269         {7200, 9720, 10800, 11880, 12600, 13320, 5400, 6480},
0270         {32400, 38880, 43200, 48600, 51840, 54000, 21600, 25920}
0271     };
0272 
0273     if (!tnrdmd || !post_bit_err || !post_bit_count)
0274         return -EINVAL;
0275 
0276     if (tnrdmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
0277         return -EINVAL;
0278 
0279     if (tnrdmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
0280         return -EINVAL;
0281 
0282     if (tnrdmd->sys != CXD2880_DTV_SYS_DVBT2)
0283         return -EINVAL;
0284 
0285     ret = slvt_freeze_reg(tnrdmd);
0286     if (ret)
0287         return ret;
0288 
0289     ret = tnrdmd->io->write_reg(tnrdmd->io,
0290                     CXD2880_IO_TGT_DMD,
0291                     0x00, 0x0b);
0292     if (ret) {
0293         slvt_unfreeze_reg(tnrdmd);
0294         return ret;
0295     }
0296 
0297     ret = tnrdmd->io->read_regs(tnrdmd->io,
0298                     CXD2880_IO_TGT_DMD,
0299                     0x15, data, 3);
0300     if (ret) {
0301         slvt_unfreeze_reg(tnrdmd);
0302         return ret;
0303     }
0304 
0305     if (!(data[0] & 0x40)) {
0306         slvt_unfreeze_reg(tnrdmd);
0307         return -EAGAIN;
0308     }
0309 
0310     *post_bit_err =
0311         ((data[0] & 0x3f) << 16) | (data[1] << 8) | data[2];
0312 
0313     ret = tnrdmd->io->read_regs(tnrdmd->io,
0314                     CXD2880_IO_TGT_DMD,
0315                     0x9d, data, 1);
0316     if (ret) {
0317         slvt_unfreeze_reg(tnrdmd);
0318         return ret;
0319     }
0320 
0321     plp_code_rate =
0322     (enum cxd2880_dvbt2_plp_code_rate)(data[0] & 0x07);
0323 
0324     ret = tnrdmd->io->read_regs(tnrdmd->io,
0325                     CXD2880_IO_TGT_DMD,
0326                     0xa0, data, 1);
0327     if (ret) {
0328         slvt_unfreeze_reg(tnrdmd);
0329         return ret;
0330     }
0331 
0332     plp_fec_type = (enum cxd2880_dvbt2_plp_fec)(data[0] & 0x03);
0333 
0334     slvt_unfreeze_reg(tnrdmd);
0335 
0336     ret = tnrdmd->io->write_reg(tnrdmd->io,
0337                     CXD2880_IO_TGT_DMD,
0338                     0x00, 0x20);
0339     if (ret)
0340         return ret;
0341 
0342     ret = tnrdmd->io->read_regs(tnrdmd->io,
0343                     CXD2880_IO_TGT_DMD,
0344                     0x72, data, 1);
0345     if (ret)
0346         return ret;
0347 
0348     period_exp = data[0] & 0x0f;
0349 
0350     if (plp_fec_type > CXD2880_DVBT2_FEC_LDPC_64K ||
0351         plp_code_rate > CXD2880_DVBT2_R2_5)
0352         return -EAGAIN;
0353 
0354     n_bch = n_bch_bits_lookup[plp_fec_type][plp_code_rate];
0355 
0356     if (*post_bit_err > ((1U << period_exp) * n_bch))
0357         return -EAGAIN;
0358 
0359     *post_bit_count = (1U << period_exp) * n_bch;
0360 
0361     return 0;
0362 }
0363 
0364 static int cxd2880_read_block_err_t(struct cxd2880_tnrdmd *tnrdmd,
0365                     u32 *block_err,
0366                     u32 *block_count)
0367 {
0368     u8 rdata[3];
0369     int ret;
0370 
0371     if (!tnrdmd || !block_err || !block_count)
0372         return -EINVAL;
0373 
0374     if (tnrdmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
0375         return -EINVAL;
0376 
0377     if (tnrdmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
0378         return -EINVAL;
0379 
0380     if (tnrdmd->sys != CXD2880_DTV_SYS_DVBT)
0381         return -EINVAL;
0382 
0383     ret = tnrdmd->io->write_reg(tnrdmd->io,
0384                     CXD2880_IO_TGT_DMD,
0385                     0x00, 0x0d);
0386     if (ret)
0387         return ret;
0388 
0389     ret = tnrdmd->io->read_regs(tnrdmd->io,
0390                     CXD2880_IO_TGT_DMD,
0391                     0x18, rdata, 3);
0392     if (ret)
0393         return ret;
0394 
0395     if ((rdata[0] & 0x01) == 0)
0396         return -EAGAIN;
0397 
0398     *block_err = (rdata[1] << 8) | rdata[2];
0399 
0400     ret = tnrdmd->io->write_reg(tnrdmd->io,
0401                     CXD2880_IO_TGT_DMD,
0402                     0x00, 0x10);
0403     if (ret)
0404         return ret;
0405 
0406     ret = tnrdmd->io->read_regs(tnrdmd->io,
0407                     CXD2880_IO_TGT_DMD,
0408                     0x5c, rdata, 1);
0409     if (ret)
0410         return ret;
0411 
0412     *block_count = 1U << (rdata[0] & 0x0f);
0413 
0414     if ((*block_count == 0) || (*block_err > *block_count))
0415         return -EAGAIN;
0416 
0417     return 0;
0418 }
0419 
0420 static int cxd2880_read_block_err_t2(struct cxd2880_tnrdmd *tnrdmd,
0421                      u32 *block_err,
0422                      u32 *block_count)
0423 {
0424     u8 rdata[3];
0425     int ret;
0426 
0427     if (!tnrdmd || !block_err || !block_count)
0428         return -EINVAL;
0429 
0430     if (tnrdmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
0431         return -EINVAL;
0432 
0433     if (tnrdmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
0434         return -EINVAL;
0435     if (tnrdmd->sys != CXD2880_DTV_SYS_DVBT2)
0436         return -EINVAL;
0437 
0438     ret = tnrdmd->io->write_reg(tnrdmd->io,
0439                     CXD2880_IO_TGT_DMD,
0440                     0x00, 0x0b);
0441     if (ret)
0442         return ret;
0443 
0444     ret = tnrdmd->io->read_regs(tnrdmd->io,
0445                     CXD2880_IO_TGT_DMD,
0446                     0x18, rdata, 3);
0447     if (ret)
0448         return ret;
0449 
0450     if ((rdata[0] & 0x01) == 0)
0451         return -EAGAIN;
0452 
0453     *block_err = (rdata[1] << 8) | rdata[2];
0454 
0455     ret = tnrdmd->io->write_reg(tnrdmd->io,
0456                     CXD2880_IO_TGT_DMD,
0457                     0x00, 0x24);
0458     if (ret)
0459         return ret;
0460 
0461     ret = tnrdmd->io->read_regs(tnrdmd->io,
0462                     CXD2880_IO_TGT_DMD,
0463                     0xdc, rdata, 1);
0464     if (ret)
0465         return ret;
0466 
0467     *block_count = 1U << (rdata[0] & 0x0f);
0468 
0469     if ((*block_count == 0) || (*block_err > *block_count))
0470         return -EAGAIN;
0471 
0472     return 0;
0473 }
0474 
0475 static void cxd2880_release(struct dvb_frontend *fe)
0476 {
0477     struct cxd2880_priv *priv = NULL;
0478 
0479     if (!fe) {
0480         pr_err("invalid arg.\n");
0481         return;
0482     }
0483     priv = fe->demodulator_priv;
0484     kfree(priv);
0485 }
0486 
0487 static int cxd2880_init(struct dvb_frontend *fe)
0488 {
0489     int ret;
0490     struct cxd2880_priv *priv = NULL;
0491     struct cxd2880_tnrdmd_create_param create_param;
0492 
0493     if (!fe) {
0494         pr_err("invalid arg.\n");
0495         return -EINVAL;
0496     }
0497 
0498     priv = fe->demodulator_priv;
0499 
0500     create_param.ts_output_if = CXD2880_TNRDMD_TSOUT_IF_SPI;
0501     create_param.xtal_share_type = CXD2880_TNRDMD_XTAL_SHARE_NONE;
0502     create_param.en_internal_ldo = 1;
0503     create_param.xosc_cap = 18;
0504     create_param.xosc_i = 8;
0505     create_param.stationary_use = 1;
0506 
0507     mutex_lock(priv->spi_mutex);
0508     if (priv->tnrdmd.io != &priv->regio) {
0509         ret = cxd2880_tnrdmd_create(&priv->tnrdmd,
0510                         &priv->regio, &create_param);
0511         if (ret) {
0512             mutex_unlock(priv->spi_mutex);
0513             pr_info("cxd2880 tnrdmd create failed %d\n", ret);
0514             return ret;
0515         }
0516     }
0517     ret = cxd2880_integ_init(&priv->tnrdmd);
0518     if (ret) {
0519         mutex_unlock(priv->spi_mutex);
0520         pr_err("cxd2880 integ init failed %d\n", ret);
0521         return ret;
0522     }
0523 
0524     ret = cxd2880_tnrdmd_set_cfg(&priv->tnrdmd,
0525                      CXD2880_TNRDMD_CFG_TSPIN_CURRENT,
0526                      0x00);
0527     if (ret) {
0528         mutex_unlock(priv->spi_mutex);
0529         pr_err("cxd2880 set config failed %d\n", ret);
0530         return ret;
0531     }
0532     mutex_unlock(priv->spi_mutex);
0533 
0534     pr_debug("OK.\n");
0535 
0536     return ret;
0537 }
0538 
0539 static int cxd2880_sleep(struct dvb_frontend *fe)
0540 {
0541     int ret;
0542     struct cxd2880_priv *priv = NULL;
0543 
0544     if (!fe) {
0545         pr_err("invalid arg\n");
0546         return -EINVAL;
0547     }
0548 
0549     priv = fe->demodulator_priv;
0550 
0551     mutex_lock(priv->spi_mutex);
0552     ret = cxd2880_tnrdmd_sleep(&priv->tnrdmd);
0553     mutex_unlock(priv->spi_mutex);
0554 
0555     pr_debug("tnrdmd_sleep ret %d\n", ret);
0556 
0557     return ret;
0558 }
0559 
0560 static int cxd2880_read_signal_strength(struct dvb_frontend *fe,
0561                     u16 *strength)
0562 {
0563     int ret;
0564     struct cxd2880_priv *priv = NULL;
0565     struct dtv_frontend_properties *c = NULL;
0566     int level = 0;
0567 
0568     if (!fe || !strength) {
0569         pr_err("invalid arg\n");
0570         return -EINVAL;
0571     }
0572 
0573     priv = fe->demodulator_priv;
0574     c = &fe->dtv_property_cache;
0575 
0576     mutex_lock(priv->spi_mutex);
0577     if (c->delivery_system == SYS_DVBT ||
0578         c->delivery_system == SYS_DVBT2) {
0579         ret = cxd2880_tnrdmd_mon_rf_lvl(&priv->tnrdmd, &level);
0580     } else {
0581         pr_debug("invalid system\n");
0582         mutex_unlock(priv->spi_mutex);
0583         return -EINVAL;
0584     }
0585     mutex_unlock(priv->spi_mutex);
0586 
0587     level /= 125;
0588     /*
0589      * level should be between -105dBm and -30dBm.
0590      * E.g. they should be between:
0591      * -105000/125 = -840 and -30000/125 = -240
0592      */
0593     level = clamp(level, -840, -240);
0594     /* scale value to 0x0000-0xffff */
0595     *strength = ((level + 840) * 0xffff) / (-240 + 840);
0596 
0597     if (ret)
0598         pr_debug("ret = %d\n", ret);
0599 
0600     return ret;
0601 }
0602 
0603 static int cxd2880_read_snr(struct dvb_frontend *fe, u16 *snr)
0604 {
0605     int ret;
0606     int snrvalue = 0;
0607     struct cxd2880_priv *priv = NULL;
0608     struct dtv_frontend_properties *c = NULL;
0609 
0610     if (!fe || !snr) {
0611         pr_err("invalid arg\n");
0612         return -EINVAL;
0613     }
0614 
0615     priv = fe->demodulator_priv;
0616     c = &fe->dtv_property_cache;
0617 
0618     mutex_lock(priv->spi_mutex);
0619     if (c->delivery_system == SYS_DVBT) {
0620         ret = cxd2880_tnrdmd_dvbt_mon_snr(&priv->tnrdmd,
0621                           &snrvalue);
0622     } else if (c->delivery_system == SYS_DVBT2) {
0623         ret = cxd2880_tnrdmd_dvbt2_mon_snr(&priv->tnrdmd,
0624                            &snrvalue);
0625     } else {
0626         pr_err("invalid system\n");
0627         mutex_unlock(priv->spi_mutex);
0628         return -EINVAL;
0629     }
0630     mutex_unlock(priv->spi_mutex);
0631 
0632     if (snrvalue < 0)
0633         snrvalue = 0;
0634     *snr = snrvalue;
0635 
0636     if (ret)
0637         pr_debug("ret = %d\n", ret);
0638 
0639     return ret;
0640 }
0641 
0642 static int cxd2880_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
0643 {
0644     int ret;
0645     struct cxd2880_priv *priv = NULL;
0646     struct dtv_frontend_properties *c = NULL;
0647 
0648     if (!fe || !ucblocks) {
0649         pr_err("invalid arg\n");
0650         return -EINVAL;
0651     }
0652 
0653     priv = fe->demodulator_priv;
0654     c = &fe->dtv_property_cache;
0655 
0656     mutex_lock(priv->spi_mutex);
0657     if (c->delivery_system == SYS_DVBT) {
0658         ret = cxd2880_tnrdmd_dvbt_mon_packet_error_number(&priv->tnrdmd,
0659                                   ucblocks);
0660     } else if (c->delivery_system == SYS_DVBT2) {
0661         ret = cxd2880_tnrdmd_dvbt2_mon_packet_error_number(&priv->tnrdmd,
0662                                    ucblocks);
0663     } else {
0664         pr_err("invalid system\n");
0665         mutex_unlock(priv->spi_mutex);
0666         return -EINVAL;
0667     }
0668     mutex_unlock(priv->spi_mutex);
0669 
0670     if (ret)
0671         pr_debug("ret = %d\n", ret);
0672 
0673     return ret;
0674 }
0675 
0676 static int cxd2880_read_ber(struct dvb_frontend *fe, u32 *ber)
0677 {
0678     *ber = 0;
0679 
0680     return 0;
0681 }
0682 
0683 static int cxd2880_set_ber_per_period_t(struct dvb_frontend *fe)
0684 {
0685     int ret;
0686     struct cxd2880_priv *priv;
0687     struct cxd2880_dvbt_tpsinfo info;
0688     enum cxd2880_dtv_bandwidth bw;
0689     u32 pre_ber_rate = 0;
0690     u32 post_ber_rate = 0;
0691     u32 ucblock_rate = 0;
0692     u32 mes_exp = 0;
0693     static const int cr_table[5] = {31500, 42000, 47250, 52500, 55125};
0694     static const int denominator_tbl[4] = {125664, 129472, 137088, 152320};
0695 
0696     if (!fe) {
0697         pr_err("invalid arg\n");
0698         return -EINVAL;
0699     }
0700 
0701     priv = fe->demodulator_priv;
0702     bw = priv->dvbt_tune_param.bandwidth;
0703 
0704     ret = cxd2880_tnrdmd_dvbt_mon_tps_info(&priv->tnrdmd,
0705                            &info);
0706     if (ret) {
0707         pr_err("tps monitor error ret = %d\n", ret);
0708         info.hierarchy = CXD2880_DVBT_HIERARCHY_NON;
0709         info.constellation = CXD2880_DVBT_CONSTELLATION_QPSK;
0710         info.guard = CXD2880_DVBT_GUARD_1_4;
0711         info.rate_hp = CXD2880_DVBT_CODERATE_1_2;
0712         info.rate_lp = CXD2880_DVBT_CODERATE_1_2;
0713     }
0714 
0715     if (info.hierarchy == CXD2880_DVBT_HIERARCHY_NON) {
0716         pre_ber_rate = 63000000 * bw * (info.constellation * 2 + 2) /
0717                    denominator_tbl[info.guard];
0718 
0719         post_ber_rate = 1000 * cr_table[info.rate_hp] * bw *
0720                 (info.constellation * 2 + 2) /
0721                 denominator_tbl[info.guard];
0722 
0723         ucblock_rate = 875 * cr_table[info.rate_hp] * bw *
0724                    (info.constellation * 2 + 2) /
0725                    denominator_tbl[info.guard];
0726     } else {
0727         u8 data = 0;
0728         struct cxd2880_tnrdmd *tnrdmd = &priv->tnrdmd;
0729 
0730         ret = tnrdmd->io->write_reg(tnrdmd->io,
0731                         CXD2880_IO_TGT_DMD,
0732                         0x00, 0x10);
0733         if (!ret) {
0734             ret = tnrdmd->io->read_regs(tnrdmd->io,
0735                             CXD2880_IO_TGT_DMD,
0736                             0x67, &data, 1);
0737             if (ret)
0738                 data = 0x00;
0739         } else {
0740             data = 0x00;
0741         }
0742 
0743         if (data & 0x01) { /* Low priority */
0744             pre_ber_rate =
0745                 63000000 * bw * (info.constellation * 2 + 2) /
0746                 denominator_tbl[info.guard];
0747 
0748             post_ber_rate = 1000 * cr_table[info.rate_lp] * bw *
0749                     (info.constellation * 2 + 2) /
0750                     denominator_tbl[info.guard];
0751 
0752             ucblock_rate = (1000 * 7 / 8) * cr_table[info.rate_lp] *
0753                        bw * (info.constellation * 2 + 2) /
0754                        denominator_tbl[info.guard];
0755         } else { /* High priority */
0756             pre_ber_rate =
0757                 63000000 * bw * 2 / denominator_tbl[info.guard];
0758 
0759             post_ber_rate = 1000 * cr_table[info.rate_hp] * bw * 2 /
0760                     denominator_tbl[info.guard];
0761 
0762             ucblock_rate = (1000 * 7 / 8) * cr_table[info.rate_hp] *
0763                     bw * 2 / denominator_tbl[info.guard];
0764         }
0765     }
0766 
0767     mes_exp = pre_ber_rate < 8192 ? 8 : intlog2(pre_ber_rate) >> 24;
0768     priv->pre_ber_interval =
0769         ((1U << mes_exp) * 1000 + (pre_ber_rate / 2)) /
0770         pre_ber_rate;
0771     cxd2880_tnrdmd_set_cfg(&priv->tnrdmd,
0772                    CXD2880_TNRDMD_CFG_DVBT_VBER_PERIOD,
0773                    mes_exp == 8 ? 0 : mes_exp - 12);
0774 
0775     mes_exp = intlog2(post_ber_rate) >> 24;
0776     priv->post_ber_interval =
0777         ((1U << mes_exp) * 1000 + (post_ber_rate / 2)) /
0778         post_ber_rate;
0779     cxd2880_tnrdmd_set_cfg(&priv->tnrdmd,
0780                    CXD2880_TNRDMD_CFG_DVBT_BERN_PERIOD,
0781                    mes_exp);
0782 
0783     mes_exp = intlog2(ucblock_rate) >> 24;
0784     priv->ucblock_interval =
0785         ((1U << mes_exp) * 1000 + (ucblock_rate / 2)) /
0786         ucblock_rate;
0787     cxd2880_tnrdmd_set_cfg(&priv->tnrdmd,
0788                    CXD2880_TNRDMD_CFG_DVBT_PER_MES,
0789                    mes_exp);
0790 
0791     return 0;
0792 }
0793 
0794 static int cxd2880_set_ber_per_period_t2(struct dvb_frontend *fe)
0795 {
0796     int ret;
0797     struct cxd2880_priv *priv;
0798     struct cxd2880_dvbt2_l1pre l1pre;
0799     struct cxd2880_dvbt2_l1post l1post;
0800     struct cxd2880_dvbt2_plp plp;
0801     struct cxd2880_dvbt2_bbheader bbheader;
0802     enum cxd2880_dtv_bandwidth bw = CXD2880_DTV_BW_1_7_MHZ;
0803     u32 pre_ber_rate = 0;
0804     u32 post_ber_rate = 0;
0805     u32 ucblock_rate = 0;
0806     u32 mes_exp = 0;
0807     u32 term_a = 0;
0808     u32 term_b = 0;
0809     u32 denominator = 0;
0810     static const u32 gi_tbl[7] = {32, 64, 128, 256, 8, 152, 76};
0811     static const u8 n_tbl[6] = {8, 2, 4, 16, 1, 1};
0812     static const u8 mode_tbl[6] = {2, 8, 4, 1, 16, 32};
0813     static const u32 kbch_tbl[2][8] = {
0814         {6952, 9472, 10552, 11632, 12352, 13072, 5152, 6232},
0815         {32128, 38608, 42960, 48328, 51568, 53760, 0, 0}
0816     };
0817 
0818     if (!fe) {
0819         pr_err("invalid arg\n");
0820         return -EINVAL;
0821     }
0822 
0823     priv = fe->demodulator_priv;
0824     bw = priv->dvbt2_tune_param.bandwidth;
0825 
0826     ret = cxd2880_tnrdmd_dvbt2_mon_l1_pre(&priv->tnrdmd, &l1pre);
0827     if (ret) {
0828         pr_info("l1 pre error\n");
0829         goto error_ber_setting;
0830     }
0831 
0832     ret = cxd2880_tnrdmd_dvbt2_mon_active_plp(&priv->tnrdmd,
0833                           CXD2880_DVBT2_PLP_DATA, &plp);
0834     if (ret) {
0835         pr_info("plp info error\n");
0836         goto error_ber_setting;
0837     }
0838 
0839     ret = cxd2880_tnrdmd_dvbt2_mon_l1_post(&priv->tnrdmd, &l1post);
0840     if (ret) {
0841         pr_info("l1 post error\n");
0842         goto error_ber_setting;
0843     }
0844 
0845     term_a =
0846         (mode_tbl[l1pre.fft_mode] * (1024 + gi_tbl[l1pre.gi])) *
0847         (l1pre.num_symbols + n_tbl[l1pre.fft_mode]) + 2048;
0848 
0849     if (l1pre.mixed && l1post.fef_intvl) {
0850         term_b = (l1post.fef_length + (l1post.fef_intvl / 2)) /
0851              l1post.fef_intvl;
0852     } else {
0853         term_b = 0;
0854     }
0855 
0856     switch (bw) {
0857     case CXD2880_DTV_BW_1_7_MHZ:
0858         denominator = ((term_a + term_b) * 71 + (131 / 2)) / 131;
0859         break;
0860     case CXD2880_DTV_BW_5_MHZ:
0861         denominator = ((term_a + term_b) * 7 + 20) / 40;
0862         break;
0863     case CXD2880_DTV_BW_6_MHZ:
0864         denominator = ((term_a + term_b) * 7 + 24) / 48;
0865         break;
0866     case CXD2880_DTV_BW_7_MHZ:
0867         denominator = ((term_a + term_b) + 4) / 8;
0868         break;
0869     case CXD2880_DTV_BW_8_MHZ:
0870     default:
0871         denominator = ((term_a + term_b) * 7 + 32) / 64;
0872         break;
0873     }
0874 
0875     if (plp.til_type && plp.til_len) {
0876         pre_ber_rate =
0877             (plp.num_blocks_max * 1000000 + (denominator / 2)) /
0878             denominator;
0879         pre_ber_rate = (pre_ber_rate + (plp.til_len / 2)) /
0880                    plp.til_len;
0881     } else {
0882         pre_ber_rate =
0883             (plp.num_blocks_max * 1000000 + (denominator / 2)) /
0884             denominator;
0885     }
0886 
0887     post_ber_rate = pre_ber_rate;
0888 
0889     mes_exp = intlog2(pre_ber_rate) >> 24;
0890     priv->pre_ber_interval =
0891         ((1U << mes_exp) * 1000 + (pre_ber_rate / 2)) /
0892         pre_ber_rate;
0893     cxd2880_tnrdmd_set_cfg(&priv->tnrdmd,
0894                    CXD2880_TNRDMD_CFG_DVBT2_LBER_MES,
0895                    mes_exp);
0896 
0897     mes_exp = intlog2(post_ber_rate) >> 24;
0898     priv->post_ber_interval =
0899         ((1U << mes_exp) * 1000 + (post_ber_rate / 2)) /
0900         post_ber_rate;
0901     cxd2880_tnrdmd_set_cfg(&priv->tnrdmd,
0902                    CXD2880_TNRDMD_CFG_DVBT2_BBER_MES,
0903                    mes_exp);
0904 
0905     ret = cxd2880_tnrdmd_dvbt2_mon_bbheader(&priv->tnrdmd,
0906                         CXD2880_DVBT2_PLP_DATA,
0907                         &bbheader);
0908     if (ret) {
0909         pr_info("bb header error\n");
0910         goto error_ucblock_setting;
0911     }
0912 
0913     if (bbheader.plp_mode == CXD2880_DVBT2_PLP_MODE_NM) {
0914         if (!bbheader.issy_indicator) {
0915             ucblock_rate =
0916                 (pre_ber_rate * kbch_tbl[plp.fec][plp.plp_cr] +
0917                 752) / 1504;
0918         } else {
0919             ucblock_rate =
0920                 (pre_ber_rate * kbch_tbl[plp.fec][plp.plp_cr] +
0921                 764) / 1528;
0922         }
0923     } else if (bbheader.plp_mode == CXD2880_DVBT2_PLP_MODE_HEM) {
0924         ucblock_rate =
0925             (pre_ber_rate * kbch_tbl[plp.fec][plp.plp_cr] + 748) /
0926             1496;
0927     } else {
0928         pr_info("plp mode is not Normal or HEM\n");
0929         goto error_ucblock_setting;
0930     }
0931 
0932     mes_exp = intlog2(ucblock_rate) >> 24;
0933     priv->ucblock_interval =
0934         ((1U << mes_exp) * 1000 + (ucblock_rate / 2)) /
0935         ucblock_rate;
0936     cxd2880_tnrdmd_set_cfg(&priv->tnrdmd,
0937                    CXD2880_TNRDMD_CFG_DVBT2_PER_MES,
0938                    mes_exp);
0939 
0940     return 0;
0941 
0942 error_ber_setting:
0943     priv->pre_ber_interval = 1000;
0944     cxd2880_tnrdmd_set_cfg(&priv->tnrdmd,
0945                      CXD2880_TNRDMD_CFG_DVBT2_LBER_MES, 0);
0946 
0947     priv->post_ber_interval = 1000;
0948     cxd2880_tnrdmd_set_cfg(&priv->tnrdmd,
0949                    CXD2880_TNRDMD_CFG_DVBT2_BBER_MES, 0);
0950 
0951 error_ucblock_setting:
0952     priv->ucblock_interval = 1000;
0953     cxd2880_tnrdmd_set_cfg(&priv->tnrdmd,
0954                    CXD2880_TNRDMD_CFG_DVBT2_PER_MES, 8);
0955 
0956     return 0;
0957 }
0958 
0959 static int cxd2880_dvbt_tune(struct cxd2880_tnrdmd *tnr_dmd,
0960                  struct cxd2880_dvbt_tune_param
0961                  *tune_param)
0962 {
0963     int ret;
0964 
0965     if (!tnr_dmd || !tune_param)
0966         return -EINVAL;
0967 
0968     if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
0969         return -EINVAL;
0970 
0971     if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP &&
0972         tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
0973         return -EINVAL;
0974 
0975     atomic_set(&tnr_dmd->cancel, 0);
0976 
0977     if (tune_param->bandwidth != CXD2880_DTV_BW_5_MHZ &&
0978         tune_param->bandwidth != CXD2880_DTV_BW_6_MHZ &&
0979         tune_param->bandwidth != CXD2880_DTV_BW_7_MHZ &&
0980         tune_param->bandwidth != CXD2880_DTV_BW_8_MHZ) {
0981         return -ENOTTY;
0982     }
0983 
0984     ret = cxd2880_tnrdmd_dvbt_tune1(tnr_dmd, tune_param);
0985     if (ret)
0986         return ret;
0987 
0988     usleep_range(CXD2880_TNRDMD_WAIT_AGC_STABLE * 10000,
0989              CXD2880_TNRDMD_WAIT_AGC_STABLE * 10000 + 1000);
0990 
0991     return cxd2880_tnrdmd_dvbt_tune2(tnr_dmd, tune_param);
0992 }
0993 
0994 static int cxd2880_dvbt2_tune(struct cxd2880_tnrdmd *tnr_dmd,
0995                   struct cxd2880_dvbt2_tune_param
0996                   *tune_param)
0997 {
0998     int ret;
0999 
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 
1034 static 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 
1120 static 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 
1264 static 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 
1302 static 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 
1381 static 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 
1407 static 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 
1608 static 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 
1802 static 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 
1828 static enum dvbfe_algo cxd2880_get_frontend_algo(struct dvb_frontend *fe)
1829 {
1830     return DVBFE_ALGO_HW;
1831 }
1832 
1833 static 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 
1876 struct 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 }
1953 EXPORT_SYMBOL(cxd2880_attach);
1954 
1955 MODULE_DESCRIPTION("Sony CXD2880 DVB-T2/T tuner + demod driver");
1956 MODULE_AUTHOR("Sony Semiconductor Solutions Corporation");
1957 MODULE_LICENSE("GPL v2");