Path: blob/master/drivers/media/dvb/frontends/dib3000mb.c
15112 views
/*1* Frontend driver for mobile DVB-T demodulator DiBcom 3000M-B2* DiBcom (http://www.dibcom.fr/)3*4* Copyright (C) 2004-5 Patrick Boettcher ([email protected])5*6* based on GPL code from DibCom, which has7*8* Copyright (C) 2004 Amaury Demol for DiBcom ([email protected])9*10* This program is free software; you can redistribute it and/or11* modify it under the terms of the GNU General Public License as12* published by the Free Software Foundation, version 2.13*14* Acknowledgements15*16* Amaury Demol ([email protected]) from DiBcom for providing specs and driver17* sources, on which this driver (and the dvb-dibusb) are based.18*19* see Documentation/dvb/README.dibusb for more information20*21*/2223#include <linux/kernel.h>24#include <linux/module.h>25#include <linux/init.h>26#include <linux/delay.h>27#include <linux/string.h>28#include <linux/slab.h>2930#include "dvb_frontend.h"3132#include "dib3000.h"33#include "dib3000mb_priv.h"3435/* Version information */36#define DRIVER_VERSION "0.1"37#define DRIVER_DESC "DiBcom 3000M-B DVB-T demodulator"38#define DRIVER_AUTHOR "Patrick Boettcher, [email protected]"3940static int debug;41module_param(debug, int, 0644);42MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-able)).");4344#define deb_info(args...) dprintk(0x01,args)45#define deb_i2c(args...) dprintk(0x02,args)46#define deb_srch(args...) dprintk(0x04,args)47#define deb_info(args...) dprintk(0x01,args)48#define deb_xfer(args...) dprintk(0x02,args)49#define deb_setf(args...) dprintk(0x04,args)50#define deb_getf(args...) dprintk(0x08,args)5152static int dib3000_read_reg(struct dib3000_state *state, u16 reg)53{54u8 wb[] = { ((reg >> 8) | 0x80) & 0xff, reg & 0xff };55u8 rb[2];56struct i2c_msg msg[] = {57{ .addr = state->config.demod_address, .flags = 0, .buf = wb, .len = 2 },58{ .addr = state->config.demod_address, .flags = I2C_M_RD, .buf = rb, .len = 2 },59};6061if (i2c_transfer(state->i2c, msg, 2) != 2)62deb_i2c("i2c read error\n");6364deb_i2c("reading i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,65(rb[0] << 8) | rb[1],(rb[0] << 8) | rb[1]);6667return (rb[0] << 8) | rb[1];68}6970static int dib3000_write_reg(struct dib3000_state *state, u16 reg, u16 val)71{72u8 b[] = {73(reg >> 8) & 0xff, reg & 0xff,74(val >> 8) & 0xff, val & 0xff,75};76struct i2c_msg msg[] = {77{ .addr = state->config.demod_address, .flags = 0, .buf = b, .len = 4 }78};79deb_i2c("writing i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,val,val);8081return i2c_transfer(state->i2c,msg, 1) != 1 ? -EREMOTEIO : 0;82}8384static int dib3000_search_status(u16 irq,u16 lock)85{86if (irq & 0x02) {87if (lock & 0x01) {88deb_srch("auto search succeeded\n");89return 1; // auto search succeeded90} else {91deb_srch("auto search not successful\n");92return 0; // auto search failed93}94} else if (irq & 0x01) {95deb_srch("auto search failed\n");96return 0; // auto search failed97}98return -1; // try again99}100101/* for auto search */102static u16 dib3000_seq[2][2][2] = /* fft,gua, inv */103{ /* fft */104{ /* gua */105{ 0, 1 }, /* 0 0 { 0,1 } */106{ 3, 9 }, /* 0 1 { 0,1 } */107},108{109{ 2, 5 }, /* 1 0 { 0,1 } */110{ 6, 11 }, /* 1 1 { 0,1 } */111}112};113114static int dib3000mb_get_frontend(struct dvb_frontend* fe,115struct dvb_frontend_parameters *fep);116117static int dib3000mb_set_frontend(struct dvb_frontend* fe,118struct dvb_frontend_parameters *fep, int tuner)119{120struct dib3000_state* state = fe->demodulator_priv;121struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;122fe_code_rate_t fe_cr = FEC_NONE;123int search_state, seq;124125if (tuner && fe->ops.tuner_ops.set_params) {126fe->ops.tuner_ops.set_params(fe, fep);127if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);128129deb_setf("bandwidth: ");130switch (ofdm->bandwidth) {131case BANDWIDTH_8_MHZ:132deb_setf("8 MHz\n");133wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[2]);134wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_8mhz);135break;136case BANDWIDTH_7_MHZ:137deb_setf("7 MHz\n");138wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[1]);139wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_7mhz);140break;141case BANDWIDTH_6_MHZ:142deb_setf("6 MHz\n");143wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[0]);144wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_6mhz);145break;146case BANDWIDTH_AUTO:147return -EOPNOTSUPP;148default:149err("unknown bandwidth value.");150return -EINVAL;151}152}153wr(DIB3000MB_REG_LOCK1_MASK, DIB3000MB_LOCK1_SEARCH_4);154155deb_setf("transmission mode: ");156switch (ofdm->transmission_mode) {157case TRANSMISSION_MODE_2K:158deb_setf("2k\n");159wr(DIB3000MB_REG_FFT, DIB3000_TRANSMISSION_MODE_2K);160break;161case TRANSMISSION_MODE_8K:162deb_setf("8k\n");163wr(DIB3000MB_REG_FFT, DIB3000_TRANSMISSION_MODE_8K);164break;165case TRANSMISSION_MODE_AUTO:166deb_setf("auto\n");167break;168default:169return -EINVAL;170}171172deb_setf("guard: ");173switch (ofdm->guard_interval) {174case GUARD_INTERVAL_1_32:175deb_setf("1_32\n");176wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_32);177break;178case GUARD_INTERVAL_1_16:179deb_setf("1_16\n");180wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_16);181break;182case GUARD_INTERVAL_1_8:183deb_setf("1_8\n");184wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_8);185break;186case GUARD_INTERVAL_1_4:187deb_setf("1_4\n");188wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_4);189break;190case GUARD_INTERVAL_AUTO:191deb_setf("auto\n");192break;193default:194return -EINVAL;195}196197deb_setf("inversion: ");198switch (fep->inversion) {199case INVERSION_OFF:200deb_setf("off\n");201wr(DIB3000MB_REG_DDS_INV, DIB3000_DDS_INVERSION_OFF);202break;203case INVERSION_AUTO:204deb_setf("auto ");205break;206case INVERSION_ON:207deb_setf("on\n");208wr(DIB3000MB_REG_DDS_INV, DIB3000_DDS_INVERSION_ON);209break;210default:211return -EINVAL;212}213214deb_setf("constellation: ");215switch (ofdm->constellation) {216case QPSK:217deb_setf("qpsk\n");218wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_QPSK);219break;220case QAM_16:221deb_setf("qam16\n");222wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_16QAM);223break;224case QAM_64:225deb_setf("qam64\n");226wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_64QAM);227break;228case QAM_AUTO:229break;230default:231return -EINVAL;232}233deb_setf("hierarchy: ");234switch (ofdm->hierarchy_information) {235case HIERARCHY_NONE:236deb_setf("none ");237/* fall through */238case HIERARCHY_1:239deb_setf("alpha=1\n");240wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_1);241break;242case HIERARCHY_2:243deb_setf("alpha=2\n");244wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_2);245break;246case HIERARCHY_4:247deb_setf("alpha=4\n");248wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_4);249break;250case HIERARCHY_AUTO:251deb_setf("alpha=auto\n");252break;253default:254return -EINVAL;255}256257deb_setf("hierarchy: ");258if (ofdm->hierarchy_information == HIERARCHY_NONE) {259deb_setf("none\n");260wr(DIB3000MB_REG_VIT_HRCH, DIB3000_HRCH_OFF);261wr(DIB3000MB_REG_VIT_HP, DIB3000_SELECT_HP);262fe_cr = ofdm->code_rate_HP;263} else if (ofdm->hierarchy_information != HIERARCHY_AUTO) {264deb_setf("on\n");265wr(DIB3000MB_REG_VIT_HRCH, DIB3000_HRCH_ON);266wr(DIB3000MB_REG_VIT_HP, DIB3000_SELECT_LP);267fe_cr = ofdm->code_rate_LP;268}269deb_setf("fec: ");270switch (fe_cr) {271case FEC_1_2:272deb_setf("1_2\n");273wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_1_2);274break;275case FEC_2_3:276deb_setf("2_3\n");277wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_2_3);278break;279case FEC_3_4:280deb_setf("3_4\n");281wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_3_4);282break;283case FEC_5_6:284deb_setf("5_6\n");285wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_5_6);286break;287case FEC_7_8:288deb_setf("7_8\n");289wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_7_8);290break;291case FEC_NONE:292deb_setf("none ");293break;294case FEC_AUTO:295deb_setf("auto\n");296break;297default:298return -EINVAL;299}300301seq = dib3000_seq302[ofdm->transmission_mode == TRANSMISSION_MODE_AUTO]303[ofdm->guard_interval == GUARD_INTERVAL_AUTO]304[fep->inversion == INVERSION_AUTO];305306deb_setf("seq? %d\n", seq);307308wr(DIB3000MB_REG_SEQ, seq);309310wr(DIB3000MB_REG_ISI, seq ? DIB3000MB_ISI_INHIBIT : DIB3000MB_ISI_ACTIVATE);311312if (ofdm->transmission_mode == TRANSMISSION_MODE_2K) {313if (ofdm->guard_interval == GUARD_INTERVAL_1_8) {314wr(DIB3000MB_REG_SYNC_IMPROVEMENT, DIB3000MB_SYNC_IMPROVE_2K_1_8);315} else {316wr(DIB3000MB_REG_SYNC_IMPROVEMENT, DIB3000MB_SYNC_IMPROVE_DEFAULT);317}318319wr(DIB3000MB_REG_UNK_121, DIB3000MB_UNK_121_2K);320} else {321wr(DIB3000MB_REG_UNK_121, DIB3000MB_UNK_121_DEFAULT);322}323324wr(DIB3000MB_REG_MOBILE_ALGO, DIB3000MB_MOBILE_ALGO_OFF);325wr(DIB3000MB_REG_MOBILE_MODE_QAM, DIB3000MB_MOBILE_MODE_QAM_OFF);326wr(DIB3000MB_REG_MOBILE_MODE, DIB3000MB_MOBILE_MODE_OFF);327328wr_foreach(dib3000mb_reg_agc_bandwidth, dib3000mb_agc_bandwidth_high);329330wr(DIB3000MB_REG_ISI, DIB3000MB_ISI_ACTIVATE);331332wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_AGC + DIB3000MB_RESTART_CTRL);333wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_OFF);334335/* wait for AGC lock */336msleep(70);337338wr_foreach(dib3000mb_reg_agc_bandwidth, dib3000mb_agc_bandwidth_low);339340/* something has to be auto searched */341if (ofdm->constellation == QAM_AUTO ||342ofdm->hierarchy_information == HIERARCHY_AUTO ||343fe_cr == FEC_AUTO ||344fep->inversion == INVERSION_AUTO) {345int as_count=0;346347deb_setf("autosearch enabled.\n");348349wr(DIB3000MB_REG_ISI, DIB3000MB_ISI_INHIBIT);350351wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_AUTO_SEARCH);352wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_OFF);353354while ((search_state =355dib3000_search_status(356rd(DIB3000MB_REG_AS_IRQ_PENDING),357rd(DIB3000MB_REG_LOCK2_VALUE))) < 0 && as_count++ < 100)358msleep(1);359360deb_setf("search_state after autosearch %d after %d checks\n",search_state,as_count);361362if (search_state == 1) {363struct dvb_frontend_parameters feps;364if (dib3000mb_get_frontend(fe, &feps) == 0) {365deb_setf("reading tuning data from frontend succeeded.\n");366return dib3000mb_set_frontend(fe, &feps, 0);367}368}369370} else {371wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_CTRL);372wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_OFF);373}374375return 0;376}377378static int dib3000mb_fe_init(struct dvb_frontend* fe, int mobile_mode)379{380struct dib3000_state* state = fe->demodulator_priv;381382deb_info("dib3000mb is getting up.\n");383wr(DIB3000MB_REG_POWER_CONTROL, DIB3000MB_POWER_UP);384385wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_AGC);386387wr(DIB3000MB_REG_RESET_DEVICE, DIB3000MB_RESET_DEVICE);388wr(DIB3000MB_REG_RESET_DEVICE, DIB3000MB_RESET_DEVICE_RST);389390wr(DIB3000MB_REG_CLOCK, DIB3000MB_CLOCK_DEFAULT);391392wr(DIB3000MB_REG_ELECT_OUT_MODE, DIB3000MB_ELECT_OUT_MODE_ON);393394wr(DIB3000MB_REG_DDS_FREQ_MSB, DIB3000MB_DDS_FREQ_MSB);395wr(DIB3000MB_REG_DDS_FREQ_LSB, DIB3000MB_DDS_FREQ_LSB);396397wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[2]);398399wr_foreach(dib3000mb_reg_impulse_noise,400dib3000mb_impulse_noise_values[DIB3000MB_IMPNOISE_OFF]);401402wr_foreach(dib3000mb_reg_agc_gain, dib3000mb_default_agc_gain);403404wr(DIB3000MB_REG_PHASE_NOISE, DIB3000MB_PHASE_NOISE_DEFAULT);405406wr_foreach(dib3000mb_reg_phase_noise, dib3000mb_default_noise_phase);407408wr_foreach(dib3000mb_reg_lock_duration, dib3000mb_default_lock_duration);409410wr_foreach(dib3000mb_reg_agc_bandwidth, dib3000mb_agc_bandwidth_low);411412wr(DIB3000MB_REG_LOCK0_MASK, DIB3000MB_LOCK0_DEFAULT);413wr(DIB3000MB_REG_LOCK1_MASK, DIB3000MB_LOCK1_SEARCH_4);414wr(DIB3000MB_REG_LOCK2_MASK, DIB3000MB_LOCK2_DEFAULT);415wr(DIB3000MB_REG_SEQ, dib3000_seq[1][1][1]);416417wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_8mhz);418419wr(DIB3000MB_REG_UNK_68, DIB3000MB_UNK_68);420wr(DIB3000MB_REG_UNK_69, DIB3000MB_UNK_69);421wr(DIB3000MB_REG_UNK_71, DIB3000MB_UNK_71);422wr(DIB3000MB_REG_UNK_77, DIB3000MB_UNK_77);423wr(DIB3000MB_REG_UNK_78, DIB3000MB_UNK_78);424wr(DIB3000MB_REG_ISI, DIB3000MB_ISI_INHIBIT);425wr(DIB3000MB_REG_UNK_92, DIB3000MB_UNK_92);426wr(DIB3000MB_REG_UNK_96, DIB3000MB_UNK_96);427wr(DIB3000MB_REG_UNK_97, DIB3000MB_UNK_97);428wr(DIB3000MB_REG_UNK_106, DIB3000MB_UNK_106);429wr(DIB3000MB_REG_UNK_107, DIB3000MB_UNK_107);430wr(DIB3000MB_REG_UNK_108, DIB3000MB_UNK_108);431wr(DIB3000MB_REG_UNK_122, DIB3000MB_UNK_122);432wr(DIB3000MB_REG_MOBILE_MODE_QAM, DIB3000MB_MOBILE_MODE_QAM_OFF);433wr(DIB3000MB_REG_BERLEN, DIB3000MB_BERLEN_DEFAULT);434435wr_foreach(dib3000mb_reg_filter_coeffs, dib3000mb_filter_coeffs);436437wr(DIB3000MB_REG_MOBILE_ALGO, DIB3000MB_MOBILE_ALGO_ON);438wr(DIB3000MB_REG_MULTI_DEMOD_MSB, DIB3000MB_MULTI_DEMOD_MSB);439wr(DIB3000MB_REG_MULTI_DEMOD_LSB, DIB3000MB_MULTI_DEMOD_LSB);440441wr(DIB3000MB_REG_OUTPUT_MODE, DIB3000MB_OUTPUT_MODE_SLAVE);442443wr(DIB3000MB_REG_FIFO_142, DIB3000MB_FIFO_142);444wr(DIB3000MB_REG_MPEG2_OUT_MODE, DIB3000MB_MPEG2_OUT_MODE_188);445wr(DIB3000MB_REG_PID_PARSE, DIB3000MB_PID_PARSE_ACTIVATE);446wr(DIB3000MB_REG_FIFO, DIB3000MB_FIFO_INHIBIT);447wr(DIB3000MB_REG_FIFO_146, DIB3000MB_FIFO_146);448wr(DIB3000MB_REG_FIFO_147, DIB3000MB_FIFO_147);449450wr(DIB3000MB_REG_DATA_IN_DIVERSITY, DIB3000MB_DATA_DIVERSITY_IN_OFF);451452return 0;453}454455static int dib3000mb_get_frontend(struct dvb_frontend* fe,456struct dvb_frontend_parameters *fep)457{458struct dib3000_state* state = fe->demodulator_priv;459struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;460fe_code_rate_t *cr;461u16 tps_val;462int inv_test1,inv_test2;463u32 dds_val, threshold = 0x800000;464465if (!rd(DIB3000MB_REG_TPS_LOCK))466return 0;467468dds_val = ((rd(DIB3000MB_REG_DDS_VALUE_MSB) & 0xff) << 16) + rd(DIB3000MB_REG_DDS_VALUE_LSB);469deb_getf("DDS_VAL: %x %x %x",dds_val, rd(DIB3000MB_REG_DDS_VALUE_MSB), rd(DIB3000MB_REG_DDS_VALUE_LSB));470if (dds_val < threshold)471inv_test1 = 0;472else if (dds_val == threshold)473inv_test1 = 1;474else475inv_test1 = 2;476477dds_val = ((rd(DIB3000MB_REG_DDS_FREQ_MSB) & 0xff) << 16) + rd(DIB3000MB_REG_DDS_FREQ_LSB);478deb_getf("DDS_FREQ: %x %x %x",dds_val, rd(DIB3000MB_REG_DDS_FREQ_MSB), rd(DIB3000MB_REG_DDS_FREQ_LSB));479if (dds_val < threshold)480inv_test2 = 0;481else if (dds_val == threshold)482inv_test2 = 1;483else484inv_test2 = 2;485486fep->inversion =487((inv_test2 == 2) && (inv_test1==1 || inv_test1==0)) ||488((inv_test2 == 0) && (inv_test1==1 || inv_test1==2)) ?489INVERSION_ON : INVERSION_OFF;490491deb_getf("inversion %d %d, %d\n", inv_test2, inv_test1, fep->inversion);492493switch ((tps_val = rd(DIB3000MB_REG_TPS_QAM))) {494case DIB3000_CONSTELLATION_QPSK:495deb_getf("QPSK ");496ofdm->constellation = QPSK;497break;498case DIB3000_CONSTELLATION_16QAM:499deb_getf("QAM16 ");500ofdm->constellation = QAM_16;501break;502case DIB3000_CONSTELLATION_64QAM:503deb_getf("QAM64 ");504ofdm->constellation = QAM_64;505break;506default:507err("Unexpected constellation returned by TPS (%d)", tps_val);508break;509}510deb_getf("TPS: %d\n", tps_val);511512if (rd(DIB3000MB_REG_TPS_HRCH)) {513deb_getf("HRCH ON\n");514cr = &ofdm->code_rate_LP;515ofdm->code_rate_HP = FEC_NONE;516switch ((tps_val = rd(DIB3000MB_REG_TPS_VIT_ALPHA))) {517case DIB3000_ALPHA_0:518deb_getf("HIERARCHY_NONE ");519ofdm->hierarchy_information = HIERARCHY_NONE;520break;521case DIB3000_ALPHA_1:522deb_getf("HIERARCHY_1 ");523ofdm->hierarchy_information = HIERARCHY_1;524break;525case DIB3000_ALPHA_2:526deb_getf("HIERARCHY_2 ");527ofdm->hierarchy_information = HIERARCHY_2;528break;529case DIB3000_ALPHA_4:530deb_getf("HIERARCHY_4 ");531ofdm->hierarchy_information = HIERARCHY_4;532break;533default:534err("Unexpected ALPHA value returned by TPS (%d)", tps_val);535break;536}537deb_getf("TPS: %d\n", tps_val);538539tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_LP);540} else {541deb_getf("HRCH OFF\n");542cr = &ofdm->code_rate_HP;543ofdm->code_rate_LP = FEC_NONE;544ofdm->hierarchy_information = HIERARCHY_NONE;545546tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_HP);547}548549switch (tps_val) {550case DIB3000_FEC_1_2:551deb_getf("FEC_1_2 ");552*cr = FEC_1_2;553break;554case DIB3000_FEC_2_3:555deb_getf("FEC_2_3 ");556*cr = FEC_2_3;557break;558case DIB3000_FEC_3_4:559deb_getf("FEC_3_4 ");560*cr = FEC_3_4;561break;562case DIB3000_FEC_5_6:563deb_getf("FEC_5_6 ");564*cr = FEC_4_5;565break;566case DIB3000_FEC_7_8:567deb_getf("FEC_7_8 ");568*cr = FEC_7_8;569break;570default:571err("Unexpected FEC returned by TPS (%d)", tps_val);572break;573}574deb_getf("TPS: %d\n",tps_val);575576switch ((tps_val = rd(DIB3000MB_REG_TPS_GUARD_TIME))) {577case DIB3000_GUARD_TIME_1_32:578deb_getf("GUARD_INTERVAL_1_32 ");579ofdm->guard_interval = GUARD_INTERVAL_1_32;580break;581case DIB3000_GUARD_TIME_1_16:582deb_getf("GUARD_INTERVAL_1_16 ");583ofdm->guard_interval = GUARD_INTERVAL_1_16;584break;585case DIB3000_GUARD_TIME_1_8:586deb_getf("GUARD_INTERVAL_1_8 ");587ofdm->guard_interval = GUARD_INTERVAL_1_8;588break;589case DIB3000_GUARD_TIME_1_4:590deb_getf("GUARD_INTERVAL_1_4 ");591ofdm->guard_interval = GUARD_INTERVAL_1_4;592break;593default:594err("Unexpected Guard Time returned by TPS (%d)", tps_val);595break;596}597deb_getf("TPS: %d\n", tps_val);598599switch ((tps_val = rd(DIB3000MB_REG_TPS_FFT))) {600case DIB3000_TRANSMISSION_MODE_2K:601deb_getf("TRANSMISSION_MODE_2K ");602ofdm->transmission_mode = TRANSMISSION_MODE_2K;603break;604case DIB3000_TRANSMISSION_MODE_8K:605deb_getf("TRANSMISSION_MODE_8K ");606ofdm->transmission_mode = TRANSMISSION_MODE_8K;607break;608default:609err("unexpected transmission mode return by TPS (%d)", tps_val);610break;611}612deb_getf("TPS: %d\n", tps_val);613614return 0;615}616617static int dib3000mb_read_status(struct dvb_frontend* fe, fe_status_t *stat)618{619struct dib3000_state* state = fe->demodulator_priv;620621*stat = 0;622623if (rd(DIB3000MB_REG_AGC_LOCK))624*stat |= FE_HAS_SIGNAL;625if (rd(DIB3000MB_REG_CARRIER_LOCK))626*stat |= FE_HAS_CARRIER;627if (rd(DIB3000MB_REG_VIT_LCK))628*stat |= FE_HAS_VITERBI;629if (rd(DIB3000MB_REG_TS_SYNC_LOCK))630*stat |= (FE_HAS_SYNC | FE_HAS_LOCK);631632deb_getf("actual status is %2x\n",*stat);633634deb_getf("autoval: tps: %d, qam: %d, hrch: %d, alpha: %d, hp: %d, lp: %d, guard: %d, fft: %d cell: %d\n",635rd(DIB3000MB_REG_TPS_LOCK),636rd(DIB3000MB_REG_TPS_QAM),637rd(DIB3000MB_REG_TPS_HRCH),638rd(DIB3000MB_REG_TPS_VIT_ALPHA),639rd(DIB3000MB_REG_TPS_CODE_RATE_HP),640rd(DIB3000MB_REG_TPS_CODE_RATE_LP),641rd(DIB3000MB_REG_TPS_GUARD_TIME),642rd(DIB3000MB_REG_TPS_FFT),643rd(DIB3000MB_REG_TPS_CELL_ID));644645//*stat = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;646return 0;647}648649static int dib3000mb_read_ber(struct dvb_frontend* fe, u32 *ber)650{651struct dib3000_state* state = fe->demodulator_priv;652653*ber = ((rd(DIB3000MB_REG_BER_MSB) << 16) | rd(DIB3000MB_REG_BER_LSB));654return 0;655}656657/* see dib3000-watch dvb-apps for exact calcuations of signal_strength and snr */658static int dib3000mb_read_signal_strength(struct dvb_frontend* fe, u16 *strength)659{660struct dib3000_state* state = fe->demodulator_priv;661662*strength = rd(DIB3000MB_REG_SIGNAL_POWER) * 0xffff / 0x170;663return 0;664}665666static int dib3000mb_read_snr(struct dvb_frontend* fe, u16 *snr)667{668struct dib3000_state* state = fe->demodulator_priv;669short sigpow = rd(DIB3000MB_REG_SIGNAL_POWER);670int icipow = ((rd(DIB3000MB_REG_NOISE_POWER_MSB) & 0xff) << 16) |671rd(DIB3000MB_REG_NOISE_POWER_LSB);672*snr = (sigpow << 8) / ((icipow > 0) ? icipow : 1);673return 0;674}675676static int dib3000mb_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)677{678struct dib3000_state* state = fe->demodulator_priv;679680*unc = rd(DIB3000MB_REG_PACKET_ERROR_RATE);681return 0;682}683684static int dib3000mb_sleep(struct dvb_frontend* fe)685{686struct dib3000_state* state = fe->demodulator_priv;687deb_info("dib3000mb is going to bed.\n");688wr(DIB3000MB_REG_POWER_CONTROL, DIB3000MB_POWER_DOWN);689return 0;690}691692static int dib3000mb_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)693{694tune->min_delay_ms = 800;695return 0;696}697698static int dib3000mb_fe_init_nonmobile(struct dvb_frontend* fe)699{700return dib3000mb_fe_init(fe, 0);701}702703static int dib3000mb_set_frontend_and_tuner(struct dvb_frontend* fe, struct dvb_frontend_parameters *fep)704{705return dib3000mb_set_frontend(fe, fep, 1);706}707708static void dib3000mb_release(struct dvb_frontend* fe)709{710struct dib3000_state *state = fe->demodulator_priv;711kfree(state);712}713714/* pid filter and transfer stuff */715static int dib3000mb_pid_control(struct dvb_frontend *fe,int index, int pid,int onoff)716{717struct dib3000_state *state = fe->demodulator_priv;718pid = (onoff ? pid | DIB3000_ACTIVATE_PID_FILTERING : 0);719wr(index+DIB3000MB_REG_FIRST_PID,pid);720return 0;721}722723static int dib3000mb_fifo_control(struct dvb_frontend *fe, int onoff)724{725struct dib3000_state *state = fe->demodulator_priv;726727deb_xfer("%s fifo\n",onoff ? "enabling" : "disabling");728if (onoff) {729wr(DIB3000MB_REG_FIFO, DIB3000MB_FIFO_ACTIVATE);730} else {731wr(DIB3000MB_REG_FIFO, DIB3000MB_FIFO_INHIBIT);732}733return 0;734}735736static int dib3000mb_pid_parse(struct dvb_frontend *fe, int onoff)737{738struct dib3000_state *state = fe->demodulator_priv;739deb_xfer("%s pid parsing\n",onoff ? "enabling" : "disabling");740wr(DIB3000MB_REG_PID_PARSE,onoff);741return 0;742}743744static int dib3000mb_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr)745{746struct dib3000_state *state = fe->demodulator_priv;747if (onoff) {748wr(DIB3000MB_REG_TUNER, DIB3000_TUNER_WRITE_ENABLE(pll_addr));749} else {750wr(DIB3000MB_REG_TUNER, DIB3000_TUNER_WRITE_DISABLE(pll_addr));751}752return 0;753}754755static struct dvb_frontend_ops dib3000mb_ops;756757struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,758struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops)759{760struct dib3000_state* state = NULL;761762/* allocate memory for the internal state */763state = kzalloc(sizeof(struct dib3000_state), GFP_KERNEL);764if (state == NULL)765goto error;766767/* setup the state */768state->i2c = i2c;769memcpy(&state->config,config,sizeof(struct dib3000_config));770771/* check for the correct demod */772if (rd(DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM)773goto error;774775if (rd(DIB3000_REG_DEVICE_ID) != DIB3000MB_DEVICE_ID)776goto error;777778/* create dvb_frontend */779memcpy(&state->frontend.ops, &dib3000mb_ops, sizeof(struct dvb_frontend_ops));780state->frontend.demodulator_priv = state;781782/* set the xfer operations */783xfer_ops->pid_parse = dib3000mb_pid_parse;784xfer_ops->fifo_ctrl = dib3000mb_fifo_control;785xfer_ops->pid_ctrl = dib3000mb_pid_control;786xfer_ops->tuner_pass_ctrl = dib3000mb_tuner_pass_ctrl;787788return &state->frontend;789790error:791kfree(state);792return NULL;793}794795static struct dvb_frontend_ops dib3000mb_ops = {796797.info = {798.name = "DiBcom 3000M-B DVB-T",799.type = FE_OFDM,800.frequency_min = 44250000,801.frequency_max = 867250000,802.frequency_stepsize = 62500,803.caps = FE_CAN_INVERSION_AUTO |804FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |805FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |806FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |807FE_CAN_TRANSMISSION_MODE_AUTO |808FE_CAN_GUARD_INTERVAL_AUTO |809FE_CAN_RECOVER |810FE_CAN_HIERARCHY_AUTO,811},812813.release = dib3000mb_release,814815.init = dib3000mb_fe_init_nonmobile,816.sleep = dib3000mb_sleep,817818.set_frontend = dib3000mb_set_frontend_and_tuner,819.get_frontend = dib3000mb_get_frontend,820.get_tune_settings = dib3000mb_fe_get_tune_settings,821822.read_status = dib3000mb_read_status,823.read_ber = dib3000mb_read_ber,824.read_signal_strength = dib3000mb_read_signal_strength,825.read_snr = dib3000mb_read_snr,826.read_ucblocks = dib3000mb_read_unc_blocks,827};828829MODULE_AUTHOR(DRIVER_AUTHOR);830MODULE_DESCRIPTION(DRIVER_DESC);831MODULE_LICENSE("GPL");832833EXPORT_SYMBOL(dib3000mb_attach);834835836