819 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Frontend driver for mobile DVB-T demodulator DiBcom 3000M-B4 * DiBcom (http://www.dibcom.fr/)5 *6 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de)7 *8 * based on GPL code from DibCom, which has9 *10 * Copyright (C) 2004 Amaury Demol for DiBcom11 *12 * Acknowledgements13 *14 * Amaury Demol from DiBcom for providing specs and driver15 * sources, on which this driver (and the dvb-dibusb) are based.16 *17 * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information18 */19 20#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt21 22#include <linux/kernel.h>23#include <linux/module.h>24#include <linux/init.h>25#include <linux/delay.h>26#include <linux/string.h>27#include <linux/slab.h>28 29#include <media/dvb_frontend.h>30 31#include "dib3000.h"32#include "dib3000mb_priv.h"33 34/* Version information */35#define DRIVER_VERSION "0.1"36#define DRIVER_DESC "DiBcom 3000M-B DVB-T demodulator"37#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@posteo.de"38 39static int debug;40module_param(debug, int, 0644);41MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-able)).");42 43#define deb_info(args...) dprintk(0x01, args)44#define deb_i2c(args...) dprintk(0x02, args)45#define deb_srch(args...) dprintk(0x04, args)46#define deb_info(args...) dprintk(0x01, args)47#define deb_xfer(args...) dprintk(0x02, args)48#define deb_setf(args...) dprintk(0x04, args)49#define deb_getf(args...) dprintk(0x08, args)50 51static int dib3000_read_reg(struct dib3000_state *state, u16 reg)52{53 u8 wb[] = { ((reg >> 8) | 0x80) & 0xff, reg & 0xff };54 u8 rb[2];55 struct i2c_msg msg[] = {56 { .addr = state->config.demod_address, .flags = 0, .buf = wb, .len = 2 },57 { .addr = state->config.demod_address, .flags = I2C_M_RD, .buf = rb, .len = 2 },58 };59 60 if (i2c_transfer(state->i2c, msg, 2) != 2)61 deb_i2c("i2c read error\n");62 63 deb_i2c("reading i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,64 (rb[0] << 8) | rb[1],(rb[0] << 8) | rb[1]);65 66 return (rb[0] << 8) | rb[1];67}68 69static int dib3000_write_reg(struct dib3000_state *state, u16 reg, u16 val)70{71 u8 b[] = {72 (reg >> 8) & 0xff, reg & 0xff,73 (val >> 8) & 0xff, val & 0xff,74 };75 struct i2c_msg msg[] = {76 { .addr = state->config.demod_address, .flags = 0, .buf = b, .len = 4 }77 };78 deb_i2c("writing i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,val,val);79 80 return i2c_transfer(state->i2c,msg, 1) != 1 ? -EREMOTEIO : 0;81}82 83static int dib3000_search_status(u16 irq,u16 lock)84{85 if (irq & 0x02) {86 if (lock & 0x01) {87 deb_srch("auto search succeeded\n");88 return 1; // auto search succeeded89 } else {90 deb_srch("auto search not successful\n");91 return 0; // auto search failed92 }93 } else if (irq & 0x01) {94 deb_srch("auto search failed\n");95 return 0; // auto search failed96 }97 return -1; // try again98}99 100/* for auto search */101static u16 dib3000_seq[2][2][2] = /* fft,gua, inv */102 { /* fft */103 { /* gua */104 { 0, 1 }, /* 0 0 { 0,1 } */105 { 3, 9 }, /* 0 1 { 0,1 } */106 },107 {108 { 2, 5 }, /* 1 0 { 0,1 } */109 { 6, 11 }, /* 1 1 { 0,1 } */110 }111 };112 113static int dib3000mb_get_frontend(struct dvb_frontend* fe,114 struct dtv_frontend_properties *c);115 116static int dib3000mb_set_frontend(struct dvb_frontend *fe, int tuner)117{118 struct dib3000_state* state = fe->demodulator_priv;119 struct dtv_frontend_properties *c = &fe->dtv_property_cache;120 enum fe_code_rate fe_cr = FEC_NONE;121 int search_state, seq;122 123 if (tuner && fe->ops.tuner_ops.set_params) {124 fe->ops.tuner_ops.set_params(fe);125 if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);126 127 switch (c->bandwidth_hz) {128 case 8000000:129 wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[2]);130 wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_8mhz);131 break;132 case 7000000:133 wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[1]);134 wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_7mhz);135 break;136 case 6000000:137 wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[0]);138 wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_6mhz);139 break;140 case 0:141 return -EOPNOTSUPP;142 default:143 pr_err("unknown bandwidth value.\n");144 return -EINVAL;145 }146 deb_setf("bandwidth: %d MHZ\n", c->bandwidth_hz / 1000000);147 }148 wr(DIB3000MB_REG_LOCK1_MASK, DIB3000MB_LOCK1_SEARCH_4);149 150 switch (c->transmission_mode) {151 case TRANSMISSION_MODE_2K:152 deb_setf("transmission mode: 2k\n");153 wr(DIB3000MB_REG_FFT, DIB3000_TRANSMISSION_MODE_2K);154 break;155 case TRANSMISSION_MODE_8K:156 deb_setf("transmission mode: 8k\n");157 wr(DIB3000MB_REG_FFT, DIB3000_TRANSMISSION_MODE_8K);158 break;159 case TRANSMISSION_MODE_AUTO:160 deb_setf("transmission mode: auto\n");161 break;162 default:163 return -EINVAL;164 }165 166 switch (c->guard_interval) {167 case GUARD_INTERVAL_1_32:168 deb_setf("guard 1_32\n");169 wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_32);170 break;171 case GUARD_INTERVAL_1_16:172 deb_setf("guard 1_16\n");173 wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_16);174 break;175 case GUARD_INTERVAL_1_8:176 deb_setf("guard 1_8\n");177 wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_8);178 break;179 case GUARD_INTERVAL_1_4:180 deb_setf("guard 1_4\n");181 wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_4);182 break;183 case GUARD_INTERVAL_AUTO:184 deb_setf("guard auto\n");185 break;186 default:187 return -EINVAL;188 }189 190 switch (c->inversion) {191 case INVERSION_OFF:192 deb_setf("inversion off\n");193 wr(DIB3000MB_REG_DDS_INV, DIB3000_DDS_INVERSION_OFF);194 break;195 case INVERSION_AUTO:196 deb_setf("inversion auto\n");197 break;198 case INVERSION_ON:199 deb_setf("inversion on\n");200 wr(DIB3000MB_REG_DDS_INV, DIB3000_DDS_INVERSION_ON);201 break;202 default:203 return -EINVAL;204 }205 206 switch (c->modulation) {207 case QPSK:208 deb_setf("modulation: qpsk\n");209 wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_QPSK);210 break;211 case QAM_16:212 deb_setf("modulation: qam16\n");213 wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_16QAM);214 break;215 case QAM_64:216 deb_setf("modulation: qam64\n");217 wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_64QAM);218 break;219 case QAM_AUTO:220 break;221 default:222 return -EINVAL;223 }224 switch (c->hierarchy) {225 case HIERARCHY_NONE:226 deb_setf("hierarchy: none\n");227 fallthrough;228 case HIERARCHY_1:229 deb_setf("hierarchy: alpha=1\n");230 wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_1);231 break;232 case HIERARCHY_2:233 deb_setf("hierarchy: alpha=2\n");234 wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_2);235 break;236 case HIERARCHY_4:237 deb_setf("hierarchy: alpha=4\n");238 wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_4);239 break;240 case HIERARCHY_AUTO:241 deb_setf("hierarchy: alpha=auto\n");242 break;243 default:244 return -EINVAL;245 }246 247 if (c->hierarchy == HIERARCHY_NONE) {248 wr(DIB3000MB_REG_VIT_HRCH, DIB3000_HRCH_OFF);249 wr(DIB3000MB_REG_VIT_HP, DIB3000_SELECT_HP);250 fe_cr = c->code_rate_HP;251 } else if (c->hierarchy != HIERARCHY_AUTO) {252 wr(DIB3000MB_REG_VIT_HRCH, DIB3000_HRCH_ON);253 wr(DIB3000MB_REG_VIT_HP, DIB3000_SELECT_LP);254 fe_cr = c->code_rate_LP;255 }256 switch (fe_cr) {257 case FEC_1_2:258 deb_setf("fec: 1_2\n");259 wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_1_2);260 break;261 case FEC_2_3:262 deb_setf("fec: 2_3\n");263 wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_2_3);264 break;265 case FEC_3_4:266 deb_setf("fec: 3_4\n");267 wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_3_4);268 break;269 case FEC_5_6:270 deb_setf("fec: 5_6\n");271 wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_5_6);272 break;273 case FEC_7_8:274 deb_setf("fec: 7_8\n");275 wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_7_8);276 break;277 case FEC_NONE:278 deb_setf("fec: none\n");279 break;280 case FEC_AUTO:281 deb_setf("fec: auto\n");282 break;283 default:284 return -EINVAL;285 }286 287 seq = dib3000_seq288 [c->transmission_mode == TRANSMISSION_MODE_AUTO]289 [c->guard_interval == GUARD_INTERVAL_AUTO]290 [c->inversion == INVERSION_AUTO];291 292 deb_setf("seq? %d\n", seq);293 294 wr(DIB3000MB_REG_SEQ, seq);295 296 wr(DIB3000MB_REG_ISI, seq ? DIB3000MB_ISI_INHIBIT : DIB3000MB_ISI_ACTIVATE);297 298 if (c->transmission_mode == TRANSMISSION_MODE_2K) {299 if (c->guard_interval == GUARD_INTERVAL_1_8) {300 wr(DIB3000MB_REG_SYNC_IMPROVEMENT, DIB3000MB_SYNC_IMPROVE_2K_1_8);301 } else {302 wr(DIB3000MB_REG_SYNC_IMPROVEMENT, DIB3000MB_SYNC_IMPROVE_DEFAULT);303 }304 305 wr(DIB3000MB_REG_UNK_121, DIB3000MB_UNK_121_2K);306 } else {307 wr(DIB3000MB_REG_UNK_121, DIB3000MB_UNK_121_DEFAULT);308 }309 310 wr(DIB3000MB_REG_MOBILE_ALGO, DIB3000MB_MOBILE_ALGO_OFF);311 wr(DIB3000MB_REG_MOBILE_MODE_QAM, DIB3000MB_MOBILE_MODE_QAM_OFF);312 wr(DIB3000MB_REG_MOBILE_MODE, DIB3000MB_MOBILE_MODE_OFF);313 314 wr_foreach(dib3000mb_reg_agc_bandwidth, dib3000mb_agc_bandwidth_high);315 316 wr(DIB3000MB_REG_ISI, DIB3000MB_ISI_ACTIVATE);317 318 wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_AGC + DIB3000MB_RESTART_CTRL);319 wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_OFF);320 321 /* wait for AGC lock */322 msleep(70);323 324 wr_foreach(dib3000mb_reg_agc_bandwidth, dib3000mb_agc_bandwidth_low);325 326 /* something has to be auto searched */327 if (c->modulation == QAM_AUTO ||328 c->hierarchy == HIERARCHY_AUTO ||329 fe_cr == FEC_AUTO ||330 c->inversion == INVERSION_AUTO) {331 int as_count=0;332 333 deb_setf("autosearch enabled.\n");334 335 wr(DIB3000MB_REG_ISI, DIB3000MB_ISI_INHIBIT);336 337 wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_AUTO_SEARCH);338 wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_OFF);339 340 while ((search_state =341 dib3000_search_status(342 rd(DIB3000MB_REG_AS_IRQ_PENDING),343 rd(DIB3000MB_REG_LOCK2_VALUE))) < 0 && as_count++ < 100)344 msleep(1);345 346 deb_setf("search_state after autosearch %d after %d checks\n",347 search_state, as_count);348 349 if (search_state == 1) {350 if (dib3000mb_get_frontend(fe, c) == 0) {351 deb_setf("reading tuning data from frontend succeeded.\n");352 return dib3000mb_set_frontend(fe, 0);353 }354 }355 356 } else {357 wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_CTRL);358 wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_OFF);359 }360 361 return 0;362}363 364static int dib3000mb_fe_init(struct dvb_frontend* fe, int mobile_mode)365{366 struct dib3000_state* state = fe->demodulator_priv;367 368 deb_info("dib3000mb is getting up.\n");369 wr(DIB3000MB_REG_POWER_CONTROL, DIB3000MB_POWER_UP);370 371 wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_AGC);372 373 wr(DIB3000MB_REG_RESET_DEVICE, DIB3000MB_RESET_DEVICE);374 wr(DIB3000MB_REG_RESET_DEVICE, DIB3000MB_RESET_DEVICE_RST);375 376 wr(DIB3000MB_REG_CLOCK, DIB3000MB_CLOCK_DEFAULT);377 378 wr(DIB3000MB_REG_ELECT_OUT_MODE, DIB3000MB_ELECT_OUT_MODE_ON);379 380 wr(DIB3000MB_REG_DDS_FREQ_MSB, DIB3000MB_DDS_FREQ_MSB);381 wr(DIB3000MB_REG_DDS_FREQ_LSB, DIB3000MB_DDS_FREQ_LSB);382 383 wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[2]);384 385 wr_foreach(dib3000mb_reg_impulse_noise,386 dib3000mb_impulse_noise_values[DIB3000MB_IMPNOISE_OFF]);387 388 wr_foreach(dib3000mb_reg_agc_gain, dib3000mb_default_agc_gain);389 390 wr(DIB3000MB_REG_PHASE_NOISE, DIB3000MB_PHASE_NOISE_DEFAULT);391 392 wr_foreach(dib3000mb_reg_phase_noise, dib3000mb_default_noise_phase);393 394 wr_foreach(dib3000mb_reg_lock_duration, dib3000mb_default_lock_duration);395 396 wr_foreach(dib3000mb_reg_agc_bandwidth, dib3000mb_agc_bandwidth_low);397 398 wr(DIB3000MB_REG_LOCK0_MASK, DIB3000MB_LOCK0_DEFAULT);399 wr(DIB3000MB_REG_LOCK1_MASK, DIB3000MB_LOCK1_SEARCH_4);400 wr(DIB3000MB_REG_LOCK2_MASK, DIB3000MB_LOCK2_DEFAULT);401 wr(DIB3000MB_REG_SEQ, dib3000_seq[1][1][1]);402 403 wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_8mhz);404 405 wr(DIB3000MB_REG_UNK_68, DIB3000MB_UNK_68);406 wr(DIB3000MB_REG_UNK_69, DIB3000MB_UNK_69);407 wr(DIB3000MB_REG_UNK_71, DIB3000MB_UNK_71);408 wr(DIB3000MB_REG_UNK_77, DIB3000MB_UNK_77);409 wr(DIB3000MB_REG_UNK_78, DIB3000MB_UNK_78);410 wr(DIB3000MB_REG_ISI, DIB3000MB_ISI_INHIBIT);411 wr(DIB3000MB_REG_UNK_92, DIB3000MB_UNK_92);412 wr(DIB3000MB_REG_UNK_96, DIB3000MB_UNK_96);413 wr(DIB3000MB_REG_UNK_97, DIB3000MB_UNK_97);414 wr(DIB3000MB_REG_UNK_106, DIB3000MB_UNK_106);415 wr(DIB3000MB_REG_UNK_107, DIB3000MB_UNK_107);416 wr(DIB3000MB_REG_UNK_108, DIB3000MB_UNK_108);417 wr(DIB3000MB_REG_UNK_122, DIB3000MB_UNK_122);418 wr(DIB3000MB_REG_MOBILE_MODE_QAM, DIB3000MB_MOBILE_MODE_QAM_OFF);419 wr(DIB3000MB_REG_BERLEN, DIB3000MB_BERLEN_DEFAULT);420 421 wr_foreach(dib3000mb_reg_filter_coeffs, dib3000mb_filter_coeffs);422 423 wr(DIB3000MB_REG_MOBILE_ALGO, DIB3000MB_MOBILE_ALGO_ON);424 wr(DIB3000MB_REG_MULTI_DEMOD_MSB, DIB3000MB_MULTI_DEMOD_MSB);425 wr(DIB3000MB_REG_MULTI_DEMOD_LSB, DIB3000MB_MULTI_DEMOD_LSB);426 427 wr(DIB3000MB_REG_OUTPUT_MODE, DIB3000MB_OUTPUT_MODE_SLAVE);428 429 wr(DIB3000MB_REG_FIFO_142, DIB3000MB_FIFO_142);430 wr(DIB3000MB_REG_MPEG2_OUT_MODE, DIB3000MB_MPEG2_OUT_MODE_188);431 wr(DIB3000MB_REG_PID_PARSE, DIB3000MB_PID_PARSE_ACTIVATE);432 wr(DIB3000MB_REG_FIFO, DIB3000MB_FIFO_INHIBIT);433 wr(DIB3000MB_REG_FIFO_146, DIB3000MB_FIFO_146);434 wr(DIB3000MB_REG_FIFO_147, DIB3000MB_FIFO_147);435 436 wr(DIB3000MB_REG_DATA_IN_DIVERSITY, DIB3000MB_DATA_DIVERSITY_IN_OFF);437 438 return 0;439}440 441static int dib3000mb_get_frontend(struct dvb_frontend* fe,442 struct dtv_frontend_properties *c)443{444 struct dib3000_state* state = fe->demodulator_priv;445 enum fe_code_rate *cr;446 u16 tps_val;447 int inv_test1,inv_test2;448 u32 dds_val, threshold = 0x800000;449 450 if (!rd(DIB3000MB_REG_TPS_LOCK))451 return 0;452 453 dds_val = ((rd(DIB3000MB_REG_DDS_VALUE_MSB) & 0xff) << 16) + rd(DIB3000MB_REG_DDS_VALUE_LSB);454 deb_getf("DDS_VAL: %x %x %x\n", dds_val, rd(DIB3000MB_REG_DDS_VALUE_MSB), rd(DIB3000MB_REG_DDS_VALUE_LSB));455 if (dds_val < threshold)456 inv_test1 = 0;457 else if (dds_val == threshold)458 inv_test1 = 1;459 else460 inv_test1 = 2;461 462 dds_val = ((rd(DIB3000MB_REG_DDS_FREQ_MSB) & 0xff) << 16) + rd(DIB3000MB_REG_DDS_FREQ_LSB);463 deb_getf("DDS_FREQ: %x %x %x\n", dds_val, rd(DIB3000MB_REG_DDS_FREQ_MSB), rd(DIB3000MB_REG_DDS_FREQ_LSB));464 if (dds_val < threshold)465 inv_test2 = 0;466 else if (dds_val == threshold)467 inv_test2 = 1;468 else469 inv_test2 = 2;470 471 c->inversion =472 ((inv_test2 == 2) && (inv_test1==1 || inv_test1==0)) ||473 ((inv_test2 == 0) && (inv_test1==1 || inv_test1==2)) ?474 INVERSION_ON : INVERSION_OFF;475 476 deb_getf("inversion %d %d, %d\n", inv_test2, inv_test1, c->inversion);477 478 switch ((tps_val = rd(DIB3000MB_REG_TPS_QAM))) {479 case DIB3000_CONSTELLATION_QPSK:480 deb_getf("QPSK\n");481 c->modulation = QPSK;482 break;483 case DIB3000_CONSTELLATION_16QAM:484 deb_getf("QAM16\n");485 c->modulation = QAM_16;486 break;487 case DIB3000_CONSTELLATION_64QAM:488 deb_getf("QAM64\n");489 c->modulation = QAM_64;490 break;491 default:492 pr_err("Unexpected constellation returned by TPS (%d)\n", tps_val);493 break;494 }495 deb_getf("TPS: %d\n", tps_val);496 497 if (rd(DIB3000MB_REG_TPS_HRCH)) {498 deb_getf("HRCH ON\n");499 cr = &c->code_rate_LP;500 c->code_rate_HP = FEC_NONE;501 switch ((tps_val = rd(DIB3000MB_REG_TPS_VIT_ALPHA))) {502 case DIB3000_ALPHA_0:503 deb_getf("HIERARCHY_NONE\n");504 c->hierarchy = HIERARCHY_NONE;505 break;506 case DIB3000_ALPHA_1:507 deb_getf("HIERARCHY_1\n");508 c->hierarchy = HIERARCHY_1;509 break;510 case DIB3000_ALPHA_2:511 deb_getf("HIERARCHY_2\n");512 c->hierarchy = HIERARCHY_2;513 break;514 case DIB3000_ALPHA_4:515 deb_getf("HIERARCHY_4\n");516 c->hierarchy = HIERARCHY_4;517 break;518 default:519 pr_err("Unexpected ALPHA value returned by TPS (%d)\n", tps_val);520 break;521 }522 deb_getf("TPS: %d\n", tps_val);523 524 tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_LP);525 } else {526 deb_getf("HRCH OFF\n");527 cr = &c->code_rate_HP;528 c->code_rate_LP = FEC_NONE;529 c->hierarchy = HIERARCHY_NONE;530 531 tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_HP);532 }533 534 switch (tps_val) {535 case DIB3000_FEC_1_2:536 deb_getf("FEC_1_2\n");537 *cr = FEC_1_2;538 break;539 case DIB3000_FEC_2_3:540 deb_getf("FEC_2_3\n");541 *cr = FEC_2_3;542 break;543 case DIB3000_FEC_3_4:544 deb_getf("FEC_3_4\n");545 *cr = FEC_3_4;546 break;547 case DIB3000_FEC_5_6:548 deb_getf("FEC_5_6\n");549 *cr = FEC_4_5;550 break;551 case DIB3000_FEC_7_8:552 deb_getf("FEC_7_8\n");553 *cr = FEC_7_8;554 break;555 default:556 pr_err("Unexpected FEC returned by TPS (%d)\n", tps_val);557 break;558 }559 deb_getf("TPS: %d\n",tps_val);560 561 switch ((tps_val = rd(DIB3000MB_REG_TPS_GUARD_TIME))) {562 case DIB3000_GUARD_TIME_1_32:563 deb_getf("GUARD_INTERVAL_1_32\n");564 c->guard_interval = GUARD_INTERVAL_1_32;565 break;566 case DIB3000_GUARD_TIME_1_16:567 deb_getf("GUARD_INTERVAL_1_16\n");568 c->guard_interval = GUARD_INTERVAL_1_16;569 break;570 case DIB3000_GUARD_TIME_1_8:571 deb_getf("GUARD_INTERVAL_1_8\n");572 c->guard_interval = GUARD_INTERVAL_1_8;573 break;574 case DIB3000_GUARD_TIME_1_4:575 deb_getf("GUARD_INTERVAL_1_4\n");576 c->guard_interval = GUARD_INTERVAL_1_4;577 break;578 default:579 pr_err("Unexpected Guard Time returned by TPS (%d)\n", tps_val);580 break;581 }582 deb_getf("TPS: %d\n", tps_val);583 584 switch ((tps_val = rd(DIB3000MB_REG_TPS_FFT))) {585 case DIB3000_TRANSMISSION_MODE_2K:586 deb_getf("TRANSMISSION_MODE_2K\n");587 c->transmission_mode = TRANSMISSION_MODE_2K;588 break;589 case DIB3000_TRANSMISSION_MODE_8K:590 deb_getf("TRANSMISSION_MODE_8K\n");591 c->transmission_mode = TRANSMISSION_MODE_8K;592 break;593 default:594 pr_err("unexpected transmission mode return by TPS (%d)\n", tps_val);595 break;596 }597 deb_getf("TPS: %d\n", tps_val);598 599 return 0;600}601 602static int dib3000mb_read_status(struct dvb_frontend *fe,603 enum fe_status *stat)604{605 struct dib3000_state* state = fe->demodulator_priv;606 607 *stat = 0;608 609 if (rd(DIB3000MB_REG_AGC_LOCK))610 *stat |= FE_HAS_SIGNAL;611 if (rd(DIB3000MB_REG_CARRIER_LOCK))612 *stat |= FE_HAS_CARRIER;613 if (rd(DIB3000MB_REG_VIT_LCK))614 *stat |= FE_HAS_VITERBI;615 if (rd(DIB3000MB_REG_TS_SYNC_LOCK))616 *stat |= (FE_HAS_SYNC | FE_HAS_LOCK);617 618 deb_getf("actual status is %2x\n",*stat);619 620 deb_getf("autoval: tps: %d, qam: %d, hrch: %d, alpha: %d, hp: %d, lp: %d, guard: %d, fft: %d cell: %d\n",621 rd(DIB3000MB_REG_TPS_LOCK),622 rd(DIB3000MB_REG_TPS_QAM),623 rd(DIB3000MB_REG_TPS_HRCH),624 rd(DIB3000MB_REG_TPS_VIT_ALPHA),625 rd(DIB3000MB_REG_TPS_CODE_RATE_HP),626 rd(DIB3000MB_REG_TPS_CODE_RATE_LP),627 rd(DIB3000MB_REG_TPS_GUARD_TIME),628 rd(DIB3000MB_REG_TPS_FFT),629 rd(DIB3000MB_REG_TPS_CELL_ID));630 631 //*stat = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;632 return 0;633}634 635static int dib3000mb_read_ber(struct dvb_frontend* fe, u32 *ber)636{637 struct dib3000_state* state = fe->demodulator_priv;638 639 *ber = ((rd(DIB3000MB_REG_BER_MSB) << 16) | rd(DIB3000MB_REG_BER_LSB));640 return 0;641}642 643/* see dib3000-watch dvb-apps for exact calcuations of signal_strength and snr */644static int dib3000mb_read_signal_strength(struct dvb_frontend* fe, u16 *strength)645{646 struct dib3000_state* state = fe->demodulator_priv;647 648 *strength = rd(DIB3000MB_REG_SIGNAL_POWER) * 0xffff / 0x170;649 return 0;650}651 652static int dib3000mb_read_snr(struct dvb_frontend* fe, u16 *snr)653{654 struct dib3000_state* state = fe->demodulator_priv;655 short sigpow = rd(DIB3000MB_REG_SIGNAL_POWER);656 int icipow = ((rd(DIB3000MB_REG_NOISE_POWER_MSB) & 0xff) << 16) |657 rd(DIB3000MB_REG_NOISE_POWER_LSB);658 *snr = (sigpow << 8) / ((icipow > 0) ? icipow : 1);659 return 0;660}661 662static int dib3000mb_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)663{664 struct dib3000_state* state = fe->demodulator_priv;665 666 *unc = rd(DIB3000MB_REG_PACKET_ERROR_RATE);667 return 0;668}669 670static int dib3000mb_sleep(struct dvb_frontend* fe)671{672 struct dib3000_state* state = fe->demodulator_priv;673 deb_info("dib3000mb is going to bed.\n");674 wr(DIB3000MB_REG_POWER_CONTROL, DIB3000MB_POWER_DOWN);675 return 0;676}677 678static int dib3000mb_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)679{680 tune->min_delay_ms = 800;681 return 0;682}683 684static int dib3000mb_fe_init_nonmobile(struct dvb_frontend* fe)685{686 return dib3000mb_fe_init(fe, 0);687}688 689static int dib3000mb_set_frontend_and_tuner(struct dvb_frontend *fe)690{691 return dib3000mb_set_frontend(fe, 1);692}693 694static void dib3000mb_release(struct dvb_frontend* fe)695{696 struct dib3000_state *state = fe->demodulator_priv;697 kfree(state);698}699 700/* pid filter and transfer stuff */701static int dib3000mb_pid_control(struct dvb_frontend *fe,int index, int pid,int onoff)702{703 struct dib3000_state *state = fe->demodulator_priv;704 pid = (onoff ? pid | DIB3000_ACTIVATE_PID_FILTERING : 0);705 wr(index+DIB3000MB_REG_FIRST_PID,pid);706 return 0;707}708 709static int dib3000mb_fifo_control(struct dvb_frontend *fe, int onoff)710{711 struct dib3000_state *state = fe->demodulator_priv;712 713 deb_xfer("%s fifo\n",onoff ? "enabling" : "disabling");714 if (onoff) {715 wr(DIB3000MB_REG_FIFO, DIB3000MB_FIFO_ACTIVATE);716 } else {717 wr(DIB3000MB_REG_FIFO, DIB3000MB_FIFO_INHIBIT);718 }719 return 0;720}721 722static int dib3000mb_pid_parse(struct dvb_frontend *fe, int onoff)723{724 struct dib3000_state *state = fe->demodulator_priv;725 deb_xfer("%s pid parsing\n",onoff ? "enabling" : "disabling");726 wr(DIB3000MB_REG_PID_PARSE,onoff);727 return 0;728}729 730static int dib3000mb_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr)731{732 struct dib3000_state *state = fe->demodulator_priv;733 if (onoff) {734 wr(DIB3000MB_REG_TUNER, DIB3000_TUNER_WRITE_ENABLE(pll_addr));735 } else {736 wr(DIB3000MB_REG_TUNER, DIB3000_TUNER_WRITE_DISABLE(pll_addr));737 }738 return 0;739}740 741static const struct dvb_frontend_ops dib3000mb_ops;742 743struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,744 struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops)745{746 struct dib3000_state* state = NULL;747 748 /* allocate memory for the internal state */749 state = kzalloc(sizeof(struct dib3000_state), GFP_KERNEL);750 if (state == NULL)751 goto error;752 753 /* setup the state */754 state->i2c = i2c;755 memcpy(&state->config,config,sizeof(struct dib3000_config));756 757 /* check for the correct demod */758 if (rd(DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM)759 goto error;760 761 if (rd(DIB3000_REG_DEVICE_ID) != DIB3000MB_DEVICE_ID)762 goto error;763 764 /* create dvb_frontend */765 memcpy(&state->frontend.ops, &dib3000mb_ops, sizeof(struct dvb_frontend_ops));766 state->frontend.demodulator_priv = state;767 768 /* set the xfer operations */769 xfer_ops->pid_parse = dib3000mb_pid_parse;770 xfer_ops->fifo_ctrl = dib3000mb_fifo_control;771 xfer_ops->pid_ctrl = dib3000mb_pid_control;772 xfer_ops->tuner_pass_ctrl = dib3000mb_tuner_pass_ctrl;773 774 return &state->frontend;775 776error:777 kfree(state);778 return NULL;779}780 781static const struct dvb_frontend_ops dib3000mb_ops = {782 .delsys = { SYS_DVBT },783 .info = {784 .name = "DiBcom 3000M-B DVB-T",785 .frequency_min_hz = 44250 * kHz,786 .frequency_max_hz = 867250 * kHz,787 .frequency_stepsize_hz = 62500,788 .caps = FE_CAN_INVERSION_AUTO |789 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |790 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |791 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |792 FE_CAN_TRANSMISSION_MODE_AUTO |793 FE_CAN_GUARD_INTERVAL_AUTO |794 FE_CAN_RECOVER |795 FE_CAN_HIERARCHY_AUTO,796 },797 798 .release = dib3000mb_release,799 800 .init = dib3000mb_fe_init_nonmobile,801 .sleep = dib3000mb_sleep,802 803 .set_frontend = dib3000mb_set_frontend_and_tuner,804 .get_frontend = dib3000mb_get_frontend,805 .get_tune_settings = dib3000mb_fe_get_tune_settings,806 807 .read_status = dib3000mb_read_status,808 .read_ber = dib3000mb_read_ber,809 .read_signal_strength = dib3000mb_read_signal_strength,810 .read_snr = dib3000mb_read_snr,811 .read_ucblocks = dib3000mb_read_unc_blocks,812};813 814MODULE_AUTHOR(DRIVER_AUTHOR);815MODULE_DESCRIPTION(DRIVER_DESC);816MODULE_LICENSE("GPL");817 818EXPORT_SYMBOL_GPL(dib3000mb_attach);819