brintos

brintos / linux-shallow public Read only

0
0
Text · 45.6 KiB · a06d836 Raw
1958 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * cxd2880_top.c4 * Sony CXD2880 DVB-T2/T tuner + demodulator driver5 *6 * Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation7 */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 <linux/int_log.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	else174		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 = -240592	 */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_param961			     *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_param996			      *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_GPL(cxd2880_attach);1954 1955MODULE_DESCRIPTION("Sony CXD2880 DVB-T2/T tuner + demod driver");1956MODULE_AUTHOR("Sony Semiconductor Solutions Corporation");1957MODULE_LICENSE("GPL v2");1958