cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

cxd2880_top.c (46678B)


      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");