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