Only in linux-2.6.23.1: .config diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/frontends/cu1216.c linux-2.6.23.1.mantis/drivers/media/dvb/frontends/cu1216.c --- linux-2.6.23.1/drivers/media/dvb/frontends/cu1216.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23.1.mantis/drivers/media/dvb/frontends/cu1216.c 2007-10-15 12:45:54.000000000 +0200 @@ -0,0 +1,1056 @@ +/* + CU-1216 driver for the Mantis bridge based cards + + Copyright (C) 2005 Twinhan Technology Co. Ltd + based on the TDA 10021 driver + + Copyright (C) 1999 Convergence Integrated Media GmbH + Copyright (C) 2004 Markus Schulz + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#include +#include +#include +#include +#include +#include +#include + +#include "dvb_frontend.h" +#include "../mantis/mantis_core.h" +#include "cu1216.h" +#include "cu1216_regs.h" + +unsigned int verbose = 1; +module_param(verbose, int, 0644); +MODULE_PARM_DESC(verbose, "print AFC offset after tuning for debugging the PWM setting"); + +struct cu1216_state { + struct i2c_adapter *i2c; + struct dvb_frontend_ops ops; + + /* config settings */ + const struct cu1216_config *config; + struct dvb_frontend frontend; + + u8 pwm; + u8 reg0; + + struct dvb_frontend_parameters params; +}; + +typedef struct AC_TypeQAM_TAG { + u8 bConf; + u8 bAgcref; + u8 bLockthr; + u8 bMseth; + u8 bAref; +} AC_TypeQAM_T; + + + + +static u32 AC_uSysClk; +static u8 li_Iq, li_oldIq = 0, uc_Gain, uc_oldGain = 0; + +static void cu1216_set_symbolRate(struct dvb_frontend *fe, u16 uFreqSymb); +static void cu1216_set_QAM(struct dvb_frontend *fe, u8 bQAM); +static void cu1216_set_IQ(struct dvb_frontend *fe, u8 bSI); +static void cu1216_set_gain(struct dvb_frontend *fe, u8 bGain); +static void cu1216_clear_register(struct dvb_frontend *fe); + +#if 0 +static void cu1216_reset (struct dvb_frontend *fe); +#endif + +static int cu1216_init (struct dvb_frontend *fe); + +static int cu1216_writereg (struct cu1216_state *state, u8 reg, u8 data) +{ + u8 buf[] = { reg, data }; + + struct i2c_msg msg = { + .addr = state->config->demod_address, + .flags = 0, + .buf = buf, + .len = 2 + }; + int ret; +#if 0 + printk("cu1216 write %d: %02x\n", reg, data); +#endif + ret = i2c_transfer (state->i2c, &msg, 1); + if (ret != 1) + printk("DVB: TDA10021(%d): %s, writereg error " + "(reg == 0x%02x, val == 0x%02x, ret == %i)\n", + state->frontend.dvb->num, __FUNCTION__, reg, data, ret); + + msleep(10); + return (ret != 1) ? -EREMOTEIO : 0; +} + +static u8 cu1216_readreg (struct cu1216_state *state, u8 reg) +{ + u8 b0 [] = { reg }; + u8 b1 [] = { 0 }; + struct i2c_msg msg [] = { + { + .addr = state->config->demod_address, + .flags = 0, + .buf = b0, + .len = 1 + }, + { + .addr = state->config->demod_address, + .flags = I2C_M_RD, + .buf = b1, + .len = 1 + } + }; + int ret; + + ret = i2c_transfer(state->i2c, msg, 2); + if (ret != 2) + printk("DVB: TDA10021: %s: readreg error (ret == %i)\n", + __FUNCTION__, ret); + return b1[0]; +} + +static int cu1216_writereg_mask (struct cu1216_state *state, u8 reg, u8 mask, u8 data) +{ + u8 value; + + value = cu1216_readreg(state, reg); + + value = (value & ~mask) | (data & mask); + //value = (value & ~mask) | data ; + + return cu1216_writereg(state, reg, value); +} + + +//get access to tuner +static int lock_tuner(struct cu1216_state *state) +{ + u8 buf[2] = { 0x0f, 0x40 | 0x80 }; + struct i2c_msg msg = { + .addr = state->config->demod_address, + .flags = 0, + .buf = buf, + .len = 2 + }; + + if (i2c_transfer(state->i2c, &msg, 1) != 1) { + printk("cu1216: lock tuner fails\n"); + return -EREMOTEIO; + } + return 0; +} + +//release access from tuner +static int unlock_tuner(struct cu1216_state *state) +{ + u8 buf[2] = { 0x0f, 0x40 & 0x7f }; + struct i2c_msg msg_post = { + .addr = state->config->demod_address, + .flags = 0, + .buf = buf, + .len = 2 + }; + + if (i2c_transfer(state->i2c, &msg_post, 1) != 1) { + printk("cu1216: unlock tuner failed\n"); + return -EREMOTEIO; + } + + return 0; +} + +static void cu1216_set_symbolRate(struct dvb_frontend *fe, u16 uFreqSymb) +{ + struct cu1216_state *state = fe->demodulator_priv; + + u8 pWrite[4], bNdec, bSFil; + u32 uBDR, uBDRb, uFreqSymbInv, uFreqSymb480; + + /* Return variables */ + u32 fSysClk; + + /* calculate system frequency */ + fSysClk = OM5734_XTALFREQ_DEF * (OM5734_PLLMFACTOR_DEF + 1); + fSysClk /= (OM5734_PLLNFACTOR_DEF + 1) * (OM5734_PLLPFACTOR_DEF + 1); + + /* add 480 ppm to the SR */ + uFreqSymb480 = uFreqSymb; + uFreqSymb480 = uFreqSymb * 480; // I Don't Know why it's * 480 not + 480 + uFreqSymb480 /= 1000000L; + uFreqSymb480 = uFreqSymb + uFreqSymb480; + fSysClk = fSysClk/1000; + bNdec = 0; + bSFil = 1; + + if (((fSysClk / 123) < (uFreqSymb480 / 10)) && + ((uFreqSymb480 / 10) <= (fSysClk / 80))) + bSFil = 0; + + if (((fSysClk / 246) < (uFreqSymb480 / 10)) && + ((uFreqSymb480 / 10) <= (fSysClk / 160))) + bSFil = 0; + + if (((fSysClk / 492) < (uFreqSymb480 / 10)) && + ((uFreqSymb480 / 10) <= (fSysClk / 320))) + bSFil = 0; + + if (((fSysClk / 984) < (uFreqSymb480 / 10)) && + ((uFreqSymb480 / 10) <= (fSysClk / 640))) + bSFil = 0; + + // program SFIL + //cu1216_writereg_mask(state, AC_GAIN_IND, AC_GAIN_SFIL_MSK, (u8)(bSFil<<4)); + cu1216_writereg(state, AC_GAIN_IND, 0x23); + + // program NDEC + //cu1216_writereg_mask(state, AC_CLKCONF_IND, AC_CLKCONF_NDEC_MSK, (u8)(bNdec<<6)); + cu1216_writereg(state, AC_CLKCONF_IND, 0x0a); + + //--------------------------------------- + // program the symbol frequency registers + //--------------------------------------- + // calculate the inversion of the symbol frequency + uFreqSymbInv = fSysClk * 16; // prefer to P21/58 Ice_Deng 2003/12/20 + uFreqSymbInv >>= bNdec; // divide by 2^decim + uFreqSymbInv += uFreqSymb / 2; // rounding for division + uFreqSymbInv /= uFreqSymb; + + if (uFreqSymbInv > 255) + uFreqSymbInv = 255; + + uBDRb = 1; + uBDRb = uBDRb << (24 + bNdec); + + fSysClk = fSysClk / 10; + uBDR = uBDRb / fSysClk; + uBDR *= uFreqSymb; + + uBDRb %= fSysClk; + uBDRb *= uFreqSymb; + uBDRb /= fSysClk; + uBDR += uBDRb; + uBDR /= 10; + + // program the value in register of the symbol rate + pWrite[0] = (unsigned char)(uBDR); + pWrite[1] = (unsigned char)(uBDR >> 8); + pWrite[2] = (unsigned char)(uBDR >> 16); + pWrite[3] = (unsigned char)uFreqSymbInv; + + cu1216_writereg(state, AC_BDRLSB_IND, pWrite[0]); + cu1216_writereg(state, AC_BDRMID_IND, pWrite[1]); + cu1216_writereg(state, AC_BDRMSB_IND, pWrite[2]); + cu1216_writereg(state, AC_BDRINV_IND, pWrite[3]); +} + +/* The default is 16-QAM refer to P31/58 */ +static void cu1216_set_QAM(struct dvb_frontend *fe, u8 bQAM) +{ + struct cu1216_state *state = fe->demodulator_priv; + + AC_TypeQAM_T sTypeQAM[] = { + { 0x14, 120, 0x78, 114, 0x96 }, /* 4 QAM <=> qam=0 */ + { 0x00, 140, 0x6e, 162, 0x91 }, /* 16 QAM <=> qam=1 */ + { 0x04, 140, 0x4b, 116, 0x96 }, /* 32 QAM <=> qam=2 */ + { 0x08, 106, 0x37, 67, 0x6a }, /* 64 QAM <=> qam=3 */ + { 0x0c, 120, 0x2d, 52, 0x7e }, /* 128 QAM <=> qam=4 */ + { 0x10, 92, 0x23, 35, 0x6b }, /* 256 QAM <=> qam=5 */ + }; + + // program the modulation in CONF register + cu1216_writereg_mask(state, AC_CONF_IND, AC_CONF_QAM_MSK, sTypeQAM[bQAM].bConf); + //cu1216_writereg(state, AC_CONF_IND, 0x6b); + + cu1216_writereg(state, AC_AGCREF_IND, sTypeQAM[bQAM].bAgcref); /* AGCREF */ + cu1216_writereg(state, AC_LOCKTHR_IND, sTypeQAM[bQAM].bLockthr); /* LOCKTHR */ + cu1216_writereg(state, AC_MSETH_IND, sTypeQAM[bQAM].bMseth); /* MSETH */ + cu1216_writereg(state, AC_AREF_IND, sTypeQAM[bQAM].bAref); /* AREF */ +} + +static void cu1216_set_IQ(struct dvb_frontend *fe, u8 bSI) +{ + struct cu1216_state *state = fe->demodulator_priv; + + bSI = (bSI+1) % 2; /* Set Spectral Inversion MODE */ + + // write the ConfReg Register + cu1216_writereg_mask(state, AC_CONF_IND, AC_CONF_INVIQ_BIT, (u8)(bSI << 5)); +} + +static void cu1216_set_gain(struct dvb_frontend *fe, u8 bGain) +{ + struct cu1216_state *state = fe->demodulator_priv; + + // write the gain + cu1216_writereg_mask(state, AC_GAIN_IND, AC_GAIN_GNYQ_MSK, (u8)(bGain << 5)); +} + +static int cu1216_read_status(struct dvb_frontend *fe, fe_status_t *status) +{ + struct cu1216_state *state = fe->demodulator_priv; +#if 1 + int sync; + + *status = 0; + /* 0x11[0] == EQALGO -> Equalizer algorithms state */ + /* 0x11[1] == CARLOCK -> Carrier locked */ + /* 0x11[2] == FSYNC -> Frame synchronisation */ + /* 0x11[3] == FEL -> Front End locked */ + /* 0x11[6] == NODVB -> DVB Mode Information */ + sync = cu1216_readreg (state, 0x11); + + if (sync & 2) + *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER; + + if (sync & 4) + *status |= FE_HAS_SYNC | FE_HAS_VITERBI; + + if (sync & 8) + *status |= FE_HAS_LOCK; + + return 0; +#else + u8 uc_Index11 = 0x0; + u8 uc_Read; + u32 loopCount = 10; + + *status = 0 ; + + while (loopCount--) { + uc_Index11 = cu1216_readreg(state, 0x11); + //printk("lock status: %02x\n", uc_Index11); + uc_Read = uc_Index11 & 0x0F; + + //*status = FE_HAS_LOCK; + //*status |= FE_HAS_SIGNAL|FE_HAS_CARRIER; + //*status |= FE_HAS_SYNC|FE_HAS_VITERBI; + + if ((uc_Read == 0x0f) && (uc_Index11 != 0xFF)) { + *status = FE_HAS_LOCK ; + break; + } + //mdelay(10); + } + + return 0; +#endif +} + + +static int cu1216_read_errRate(struct dvb_frontend *fe) +{ + struct cu1216_state *state = fe->demodulator_priv; + + int cCkOffset = 0; + int iErrRyt; + + // read offset + cCkOffset = cu1216_readreg(state, 0x1d); + + // convert the value to long + if (cCkOffset < 0) + iErrRyt = (int)(0xFFFFFF00 | cCkOffset); + else + iErrRyt = (int)cCkOffset; + + // read DYN bit + cCkOffset = cu1216_readreg(state, 0x03); + + // calculate the error in ppm + iErrRyt *= 1000000; + iErrRyt /= 262144; + + if (!(cCkOffset & 0x08)) + iErrRyt /= 2; + + return iErrRyt; +} + + + +static int cu1216_read_quality(struct dvb_frontend *fe, u16 *quality) +{ + struct cu1216_state *state = fe->demodulator_priv; + + u8 tempval; + fe_status_t tunerStatus; + + cu1216_read_status(fe, &tunerStatus); + + if (tunerStatus == 0) { + *quality = 0; + return 0; + } + + tempval = cu1216_readreg(state, 0x18); + + if (tempval <= 5) { + *quality = 98; + + return 0; + + } else if(tempval <= 10) { + *quality = 108 - 2*tempval;//88 + + return 0; + } + + switch (state->params.u.qam.modulation) { + case QPSK: + case QAM_16: + if (tempval <= 110) + *quality = 60 + (110 - tempval) * 3 / 10;//0.3 + else if (tempval <= 120) + *quality = 30 + (120 - tempval) * 30 / 10; + else + *quality = (255 - tempval) * 30 / 135; + break; + case QAM_32: + if (tempval <= 72) + *quality = 60 + (72 - tempval) * 15 / 31;//0.5 + else if (tempval <= 82) + *quality = 30 + (83 - tempval) * 30 / 11; + else + *quality = (255 - tempval) * 30 / 172; + break; + default: + case QAM_64: + if (tempval <= 42) + *quality = 60 + (42- tempval) * 7 / 8;//0.875 + else if (tempval <= 52) + *quality = 30 + (52 - tempval) * 30 / 10; + else + *quality = (255-tempval)*30/203; + break; + case QAM_128: + if (tempval <= 28) + *quality = 60 + (28 - tempval) * 14 / 9;//1.5 + else if(tempval <= 34) + *quality = 30 + (34 - tempval) * 30 / 6; + else + *quality = (255 - tempval) * 30 / 221; + break; + case QAM_256: + if (tempval <= 18) + *quality = 60 + (18 - tempval) * 7 / 2;//3.5 + else if (tempval <= 22) + *quality = 30 + (22 - tempval) * 30 / 4; + else + *quality = (255 - tempval) * 30 / 233; + break; + } + + return 0; +} + + +static int cu1216_read_strength(struct dvb_frontend *fe, u16 *strength) +{ + struct cu1216_state *state = fe->demodulator_priv; + + u8 tempagc; + + tempagc = cu1216_readreg(state, AC_VAGC1_IND); + + if (tempagc > 0xF0) + *strength = 2; + else if (tempagc > 0xE5) + *strength = 4; + else if (tempagc < 0x6E) + *strength = 98; + else if (tempagc < 0x96) + *strength = 70 + (0x96 - tempagc) / 2 * 7 / 5; + else if (tempagc < 0xCD) + *strength = 14 + (0xCD - tempagc); + else + *strength = 2 + (0xE5 - tempagc) / 2; + + return 0; +} + + + +static int cu1216_read_ber(struct dvb_frontend *fe, u32 *BERvalue) +{ + struct cu1216_state *state = fe->demodulator_priv; + + u8 tempval; + + tempval = cu1216_readreg(state, 0x16); + + tempval &= 0x0f; + *BERvalue = tempval; + *BERvalue <<=8; + + tempval = cu1216_readreg(state, 0x15); + + *BERvalue += tempval; + *BERvalue <<=8; + + tempval = cu1216_readreg(state, 0x14); + + *BERvalue += tempval; + + tempval = cu1216_readreg(state, 0x10); + + switch (tempval & 0xc0) { + default: + case 0x00: /* 1,00E+05 */ + *BERvalue *= 80; + break; + case 0x40: /* 1,00E+06 */ + *BERvalue *= 10; + break; + case 0x80: /* 1,00E+07 */ + *BERvalue /= 1; + break; + case 0xc0: /* 1,00E+08 */ + *BERvalue /= 10; + break; + } + + return 0; +} + +static int cu1216_read_snr (struct dvb_frontend *fe, u16 *SNRvalue) +{ + struct cu1216_state *state = fe->demodulator_priv; + + u8 tempagc; + + tempagc = cu1216_readreg(state, 0x18); + + *SNRvalue = tempagc; + switch (state->params.u.qam.modulation) { + case QAM_16: + *SNRvalue = 195000 / (32 * (*SNRvalue) + 138) + 100; + break; + case QAM_32: + *SNRvalue = 215000 / (40 * (*SNRvalue) + 500) + 135; + break; + default: + case QAM_64: + *SNRvalue = 210000 / (40 * (*SNRvalue) + 500) + 125; + break; + case QAM_128: + *SNRvalue = 185000 / (38 * (*SNRvalue) + 400) + 138; + break; + case QAM_256: + *SNRvalue = 180000 / (100 * (*SNRvalue) + 40) + 203; + break; + } + + return 0; +} + + + +static int cu1216_read_ubk(struct dvb_frontend *fe, u32 *ubk) +{ + struct cu1216_state *state = fe->demodulator_priv; + + u8 puBytes[4]; + u32 puUBK; + + /* Implementation */ + puBytes[0] = cu1216_readreg(state, AC_CPTUNCOR_IND); + puBytes[1] = cu1216_readreg(state, AC_BERLSB_IND); + puBytes[2] = cu1216_readreg(state, AC_BERMID_IND); + puBytes[3] = cu1216_readreg(state, AC_BERMSB_IND); + + + puUBK = (puBytes[3] << 24) | (puBytes[2] << 16) | (puBytes[1] << 8) | puBytes[0]; + + /* mask the reset flag */ + puUBK &= AC_CPTUNCOR_CPTU_MSK; + + /* reset counter, if uncorrectables */ + if (puUBK) { + cu1216_writereg_mask(state, AC_RSCONF_IND, AC_RSCONF_CLBUNC_BIT, 0); + cu1216_writereg_mask(state, AC_RSCONF_IND, AC_RSCONF_CLBUNC_BIT,AC_RSCONF_CLBUNC_BIT); + } + *ubk = puUBK; + + return 0; +} + +static void cu1216_clear_register(struct dvb_frontend *fe) +{ + struct cu1216_state *state = fe->demodulator_priv; + + cu1216_writereg(state, AC_CONF_IND, 0x6a); +} + +/* +static void cu1216_reset(struct dvb_frontend *fe) +{ + struct cu1216_state *state = fe->demodulator_priv; + +// mantis_fe_reset((struct mantis_pci *) state->frontend.dvb->priv); + mantis_fe_reset((struct mantis_pci *) state->frontend.dvb->priv); + + + // set_gpio_A12A13A14(mantis, 13, 0); + // mdelay(100); + // set_gpio_A12A13A14(mantis, 13, 1); + + + switch (mantis->card_version) { + case 0x07: + mantisReg->gpio_0123 &= 0x80ffffff; + mantisReg->gpio_0123 |= 0x80000000; + mdelay(100); + mantisReg->gpio_0123 &= 0x80ffffff; + mantisReg->gpio_0123 |= 0x82000000; + break; + + case 0x08: + set_gpio_A12A13A14(mantis, 13, 0); + mdelay(100); + set_gpio_A12A13A14(mantis, 13, 1); + break; + } + DBGMSG("<demodulator_priv; + + u8 bByte; + s32 lDeltaF; + + // calculate the system frequency + AC_uSysClk = OM5734_XTALFREQ_DEF * (OM5734_PLLMFACTOR_DEF + 1); + AC_uSysClk /= (OM5734_PLLNFACTOR_DEF + 1) * (OM5734_PLLPFACTOR_DEF + 1); + + // PLL factors + // bPLL_M_Factor =0x07 + // bPLL_N_Factor =0x00 + // bPLL_P_Factor =0x03 + + cu1216_writereg(state, AC_MDIV_IND, OM5734_PLLMFACTOR_DEF); + cu1216_writereg(state, AC_NDIV_IND, OM5734_PLLNFACTOR_DEF); + cu1216_writereg(state, AC_PLL_IND, OM5734_PLLPFACTOR_DEF); + + // add by ice_Deng 2004/01/06 + cu1216_writereg(state, AC_CONTROL_IND, 0x0d); + + // enable the PLL + cu1216_writereg_mask(state, AC_PLL_IND, AC_PLL_BYPPLL_BIT, 0); + + // enable AGC2 and set PWMREF + cu1216_writereg_mask(state, AC_AGCCONF2_IND, AC_AGCCONF2_ENAGC2_BIT, AC_AGCCONF2_ENAGC2_BIT); + cu1216_writereg(state, AC_PWMREF_IND, AC_PWMREF_DEF); + + // use internal ADC + //cu1216_writereg_mask(state, AC_ADC_IND, AC_ADC_PCLK_BIT, AC_ADC_PCLK_BIT); + //cu1216_writereg_mask(state, AC_ADC_IND, AC_ADC_SW_MSK, AC_ADC_SW_DEF); + cu1216_writereg(state, AC_ADC_IND, 0x31); + cu1216_writereg(state, AC_ADC_IND, 0x31); + // use only nyquist gain + //cu1216_writereg_mask(state, AC_CLKCONF_IND, AC_CLKCONF_GAIN3_BIT, 0); + cu1216_writereg(state, AC_CLKCONF_IND, 0x0a); + // set the acquisition to +/-480ppm + //cu1216_writereg_mask(state, AC_CLKCONF_IND, AC_CLKCONF_DYN_BIT, AC_CLKCONF_DYN_BIT); + cu1216_writereg(state, AC_CLKCONF_IND, 0x0a); + // POS_AGC - not in data sheet +#if 0 + cu1216_writereg_mask(state, AC_AGCCONF1_IND, AC_AGCCONF1_POSAGC_BIT, AC_AGCCONF1_POSAGC_BIT); + // set the polarity of the PWM for the AGC + if (AC_POLAPWM1_DEF) + cu1216_writereg_mask(state, AC_AGCCONF1_IND, AC_AGCCONF1_PPWM1_BIT, AC_AGCCONF1_PPWM1_BIT); + else + cu1216_writereg_mask(state, AC_AGCCONF1_IND, AC_AGCCONF1_PPWM1_BIT, 0); +#else + cu1216_writereg(state, AC_AGCCONF1_IND, 0x23); + cu1216_writereg(state, AC_AGCCONF1_IND, 0x23); +#endif + if (AC_POLAPWM2_DEF) + cu1216_writereg_mask(state, AC_AGCCONF2_IND, AC_AGCCONF2_PPWM2_BIT, AC_AGCCONF2_PPWM2_BIT); + else + cu1216_writereg_mask(state, AC_AGCCONF2_IND, AC_AGCCONF2_PPWM2_BIT, 0); + + // set the threshold for the IF AGC + cu1216_writereg(state, AC_IFMAX_IND, AC_IFMAX_DEF); + cu1216_writereg(state, AC_IFMIN_IND, 0); //AC_IFMIN_DEF150 ; + + + // set the threshold for the TUN AGC + cu1216_writereg(state, AC_TUNMAX_IND, AC_TUNMAX_DEF); + cu1216_writereg(state, AC_TUNMIN_IND, AC_TUNMIN_DEF); + + + // set the counter of saturation to its maximun size + //cu1216_writereg_mask(state, AC_GAIN_IND, AC_GAIN_SSAT_MSK, 0x03); + cu1216_writereg(state, AC_GAIN_IND, 0x23); + + // set the MPEG output clock polarity + //cu1216_writereg_mask(state, AC_POLA1_IND, AC_POLA1_POCLK1_BIT, 1); + + //cu1216_writereg(state, 0x12, 0xa0); + + // Added By IceDeng 12/15/2004 For Ts 188 + //cu1216_writereg_mask(state, AC_POLA1_IND, 0x40, 0x40); + cu1216_writereg(state, 0x12, 0xe1); + cu1216_writereg(state, 0x12, 0xe1); + + //cyq channge star + cu1216_writereg_mask(state, AC_POLA2_IND, AC_POLA2_POCLK2_BIT, AC_POLA2_POCLK2_BIT); + + // set the position of the central coeffcient + cu1216_writereg_mask(state, AC_EQCONF1_IND, AC_EQCONF1_POSI_MSK, 0x70); + + // set the equalizer type + if (AC_EQUALTYPE_DEF) + cu1216_writereg_mask(state, AC_EQCONF1_IND, AC_EQCONF1_DFE_BIT, AC_EQUALTYPE_DEF-1); + + cu1216_writereg_mask(state, AC_EQCONF2_IND, AC_EQCONF2_SGNALGO_BIT, AC_EQCONF2_SGNALGO_BIT); + + // set ALGOD and deltaF + //57840000 = OM5734_XTALFREQ_DEF*(OM5734_PLLMFACTOR_DEF+1) / (OM5734_PLLNFACTOR_DEF+1)*(OM5734_PLLPFACTOR_DEF+1) + + lDeltaF = (s32)(AC_uSysClk * 5 / 1000); + lDeltaF /= -8; + lDeltaF += (AC_TUNFI_DEF / 1000); + lDeltaF *= 2048; + lDeltaF /= (s32)(AC_uSysClk / 1000); + + cu1216_writereg(state, AC_DELTAF1_IND, (u8)lDeltaF); + cu1216_writereg(state, AC_DELTAF2_IND, (u8)(((lDeltaF>>8) & 0x03) | AC_DELTAF2_ALGOD_BIT)); + + // set the KAGC to its maximun value + cu1216_writereg_mask(state, AC_AGCCONF1_IND, AC_AGCCONF1_KAGC_MSK, 0x03); + + // set carrier algorithm parameters and SELCAR + bByte = AC_SWEEP_DEF; + bByte |= (u8)AC_CAROFFLENGTH_DEF; + bByte |= (u8)(AC_CAROFFSTEP_DEF << 2); + //bByte |= (u8)(AC_CARRANGE_DEF << 4); + + cu1216_writereg(state, AC_SWEEP_IND, bByte); + + // TS interface 1 + bByte = AC_INTP_DEF; + if (AC_MSBFIRST1_DEF) + bByte |= AC_INTP_MSBFIRST_BIT; + if( AC_PARASER1_DEF) + bByte |= AC_INTP_INTSEL_BIT; + else + bByte |= AC_INTP_MSBFIRST_BIT; // set to 1 MSB if parallel + + if (AC_MODEAB1_DEF) { + bByte |= AC_INTP_PARMOD_BIT; + bByte |= (AC_PARADIV1_DEF << 4); + } + cu1216_writereg(state, AC_INTP_IND, bByte); + cu1216_writereg_mask(state, AC_POLA2_IND, AC_POLA2_MSBFIRST2_BIT, AC_POLA2_MSBFIRST2_BIT); + + // set the BER depth + cu1216_writereg_mask(state, AC_RSCONF_IND, AC_RSCONF_PVBER_MSK, (AC_BERDEPTH_DEF<< 6)); + + return 0; +} + +static void delay_ms_interruptible(u32 ms) +{ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ * ms / 100); +} + +static void delay_us_interruptible(u32 us) +{ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ * us / 10000); +} + + +static int cu1216_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + struct cu1216_state *state = fe->demodulator_priv; + + u8 i; + u8 QamSize = 0; + u32 ErrRate[3]; + fe_status_t value; + int status = -EINVAL; + + printk("[%s]:frequency = %d , symbol = %d , qam = %d .\n", + __func__, + params->frequency , params->u.qam.symbol_rate, + params->u.qam.modulation); + + switch (params->u.qam.modulation) { + case QPSK : + QamSize = 0; + break; + case QAM_16 : + QamSize = 1; + break; + case QAM_32 : + QamSize = 2; + break; + case QAM_64 : + QamSize = 3; + break; + case QAM_128: + QamSize = 4; + break; + case QAM_256: + QamSize = 5; + break; + default : + printk("[cu1216_set_parameters]:QAM set error!\n"); + break; + } + + if (li_oldIq >= 2) + li_oldIq = 0; + +// cu1216_reset(fe); +// FIXME ! need to do a Bridge RESET from here +// state->config->fe_reset(fe); + + //To clear the Registers in TDA10021HT + cu1216_clear_register(fe); + + //Write Frequency into tuner + lock_tuner(state); + state->config->pll_set(fe, params); + unlock_tuner(state); + + //mdelay(20); + delay_ms_interruptible(10); + + //Second step to init the cu1216ht's registers + cu1216_init(fe); + + //Write Symborate + cu1216_set_symbolRate(fe, params->u.qam.symbol_rate / 1000); + + //Write QAM + cu1216_set_QAM(fe, QamSize); + + for (i = li_oldIq; i < li_oldIq + 2; i++) { + li_Iq = i % 2; + + for (uc_Gain = 1; uc_Gain < 4; uc_Gain++) { + cu1216_set_IQ(fe, li_Iq); + + cu1216_set_gain(fe, uc_Gain); + + //udelay(50); + delay_us_interruptible(5); + + if (cu1216_read_status(fe, &value) == 0) { + + li_oldIq = li_Iq; + uc_oldGain = uc_Gain; + ErrRate[0] = cu1216_read_errRate(fe); + + if (uc_Gain < 3) { + cu1216_set_gain(fe, uc_Gain+1); + //udelay(50); + delay_us_interruptible(5); + ErrRate[1] = cu1216_read_errRate(fe); + + if (ErrRate[0] > ErrRate[1]) { + cu1216_set_gain(fe , uc_Gain); + //udelay(50); + delay_us_interruptible(5); + + } else { + uc_oldGain = uc_Gain + 1; + uc_Gain = uc_Gain + 1; + + if (uc_Gain < 3) { + cu1216_set_gain(fe, uc_Gain + 1); + + //udelay(50); + delay_us_interruptible(5); + ErrRate[2] = cu1216_read_errRate(fe); + + if (ErrRate[1] > ErrRate[2]) { + cu1216_set_gain(fe , uc_oldGain); + + //udelay(50); + delay_us_interruptible(5); + } else { + uc_oldGain = uc_Gain + 1; + } + } + } + } + goto ret; + } + } + } + + status = -1; + +ret: + + state->params = *params; + + return status ; +} + +static int cu1216_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) +{ + struct cu1216_state *state = fe->demodulator_priv; + int sync; + s8 afc = 0; + + sync = cu1216_readreg(state, 0x11); + afc = cu1216_readreg(state, 0x19); + if (verbose) { + /* AFC only valid when carrier has been recovered */ + printk(sync & 2 ? "DVB: TDA10021(%d): AFC (%d) %dHz\n" : + "DVB: TDA10021(%d): [AFC (%d) %dHz]\n", + state->frontend.dvb->num, afc, + - ((s32)p->u.qam.symbol_rate * afc) >> 10); + } + + p->inversion = HAS_INVERSION(state->reg0) ? INVERSION_ON : INVERSION_OFF; + p->u.qam.modulation = ((state->reg0 >> 2) & 7) + QAM_16; + + p->u.qam.fec_inner = FEC_NONE; + p->frequency = ((p->frequency + 31250) / 62500) * 62500; + + if (sync & 2) + p->frequency -= ((s32)p->u.qam.symbol_rate * afc) >> 10; + + return 0; +} + +static int cu1216_get_tune_settings(struct dvb_frontend *fe, + struct dvb_frontend_tune_settings *p) +{ + p->min_delay_ms = 50; + p->step_size = 0; + p->max_drift = 0; + + return 0; +} + +static int cu1216_sleep(struct dvb_frontend *fe) +{ + struct cu1216_state *state = fe->demodulator_priv; + + cu1216_writereg (state, 0x1b, 0x02); /* pdown ADC */ + cu1216_writereg (state, 0x00, 0x80); /* standby */ + + return 0; +} + +static void cu1216_release(struct dvb_frontend *fe) +{ + struct cu1216_state *state = fe->demodulator_priv; + kfree(state); +} + +static struct dvb_frontend_ops cu1216_ops; + +struct dvb_frontend *cu1216_attach(const struct cu1216_config *config, + struct i2c_adapter *i2c) +{ + struct cu1216_state *state = NULL; + + /* allocate memory for the internal state */ + state = kmalloc(sizeof (struct cu1216_state), GFP_KERNEL); + if (state == NULL) + goto error; + + /* setup the state */ + state->config = config; + state->i2c = i2c; + memcpy(&state->ops, &cu1216_ops, sizeof (struct dvb_frontend_ops)); + //state->pwm = pwm; + //state->reg0 = cu1216_inittab[0]; + + /* check if the demod is there */ + if ((cu1216_readreg(state, 0x1a) & 0xf0) != 0x70) + goto error; + + /* create dvb_frontend */ + state->frontend.ops = state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + kfree(state); + return NULL; +} + +static struct dvb_frontend_ops cu1216_ops = { + + .info = { + .name = "Philips CU1216 DVB-C", + .type = FE_QAM, + .frequency_stepsize = 62500, + .frequency_min = 51000000, + .frequency_max = 858000000, + .symbol_rate_min = (XIN / 2) / 64, /* SACLK/64 == (XIN/2)/64 */ + .symbol_rate_max = (XIN / 2) / 4, /* SACLK/4 */ +#if 0 + .frequency_tolerance = ???, + .symbol_rate_tolerance = ???, /* ppm == 8% (spec p. 5) */ +#endif + .caps = 0x400 | /* FE_CAN_QAM_4 */ + FE_CAN_QAM_16 | + FE_CAN_QAM_32 | + FE_CAN_QAM_64 | + FE_CAN_QAM_128 | + FE_CAN_QAM_256 | + FE_CAN_FEC_AUTO + }, + + .release = cu1216_release, + .init = cu1216_init_none, + .sleep = cu1216_sleep, + .set_frontend = cu1216_set_parameters, + .get_frontend = cu1216_get_frontend, + .read_status = cu1216_read_status, + .read_ber = cu1216_read_ber, + .read_signal_strength = cu1216_read_strength, + .read_snr = cu1216_read_snr, + .read_ucblocks = cu1216_read_ubk, + .get_tune_settings = cu1216_get_tune_settings, +}; + + +MODULE_DESCRIPTION("Philips CU1216 DVB-C demodulator driver"); +MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL(cu1216_attach); diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/frontends/cu1216.h linux-2.6.23.1.mantis/drivers/media/dvb/frontends/cu1216.h --- linux-2.6.23.1/drivers/media/dvb/frontends/cu1216.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23.1.mantis/drivers/media/dvb/frontends/cu1216.h 2007-10-10 17:51:19.000000000 +0200 @@ -0,0 +1,46 @@ +/* + CU-1216 driver for the Mantis bridge based cards + + Copyright (C) 2005 Twinhan Technology Co. Ltd + based on the TDA 10021 driver + + Copyright (C) 1999 Convergence Integrated Media GmbH + Copyright (C) 2004 Markus Schulz + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __CU1216_H +#define __CU1216_H + +#include + +struct cu1216_config { + /* demod i2c address */ + u8 demod_address; + + /* PLL maintenance */ + int (*pll_init)(struct dvb_frontend *fe); + int (*pll_set)(struct dvb_frontend *fe, struct dvb_frontend_parameters *params); + + int (*fe_reset)(struct dvb_frontend *fe); +}; + +extern struct dvb_frontend *cu1216_attach(const struct cu1216_config *config, struct i2c_adapter *i2c); + + +#endif //__CU1216_H diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/frontends/cu1216_regs.h linux-2.6.23.1.mantis/drivers/media/dvb/frontends/cu1216_regs.h --- linux-2.6.23.1/drivers/media/dvb/frontends/cu1216_regs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23.1.mantis/drivers/media/dvb/frontends/cu1216_regs.h 2007-10-10 17:51:19.000000000 +0200 @@ -0,0 +1,273 @@ +/* + CU-1216 driver for the Mantis bridge based cards + + Copyright (C) 2005 Twinhan Technology Co. Ltd + based on the TDA 10021 driver + + Copyright (C) 1999 Convergence Integrated Media GmbH + Copyright (C) 2004 Markus Schulz + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __CU1216_REGS_H +#define __CU1216_REGS_H + +#define XIN 57840000UL + +#define DISABLE_INVERSION(reg0) do { reg0 |= 0x20; } while (0) +#define ENABLE_INVERSION(reg0) do { reg0 &= ~0x20; } while (0) +#define HAS_INVERSION(reg0) (!(reg0 & 0x20)) + +#define FIN (XIN >> 4) + +#define C_1216_CHIP_ADDRESS 0x18 +#define C_1216_TUNER_ADDRESS 0xc0 + +#define OM5734_XTALFREQ_DEF 28920000 +#define OM5734_PLLMFACTOR_DEF 0x07 +#define OM5734_PLLNFACTOR_DEF 0x00 +#define OM5734_PLLPFACTOR_DEF 0x03 + +#define AC_POLAPWM1_DEF 0 +#define AC_POLAPWM2_DEF 0 +#define AC_IFMAX_DEF 255 +#define OM5735_IFMIN_DEF 64 +#define OM5734_IFMIN_DEF 88 +#define AC_TUNMAX_DEF 255 +#define AC_TUNMIN_DEF 0 +#define AC_IFMIN_DEF150 150 + +#define AC_EQUALTYPE_DEF 2 +#define AC_BERDEPTH_DEF 2 +#define AC_CAROFFSTEP_DEF 1 +#define AC_CAROFFLENGTH_DEF 1 +#define AC_CARRANGE_DEF 1 +#define AC_DISAFC_DEF 0 + +#define AC_IQSWAPPED_DEF 1 +#define AC_TUNID_DEF 0 +#define AC_TUNREADENA_DEF 0 +#define AC_TUNFI_DEF 36125000 + +#define AC_POCLK1_DEF 1 +#define AC_PARASER1_DEF 0 +#define AC_MSBFIRST1_DEF 0 +#define AC_MODEAB1_DEF 0 +#define AC_PARADIV1_DEF 0 +#define AC_POCLK2_DEF 1 +#define AC_PARASER2_DEF 0 + +#define OM5734_DEF 0 +#define OM5735_DEF 1 +#define CUSTOM_DEF 2 + +/* Index register definition */ +#define AC_CONF_IND 0x00 +#define AC_AGCREF_IND 0x01 +#define AC_AGCCONF1_IND 0x02 +#define AC_CLKCONF_IND 0x03 +#define AC_CARCONF_IND 0x04 +#define AC_LOCKTHR_IND 0x05 +#define AC_EQCONF1_IND 0x06 +#define AC_EQSTEP_IND 0X07 +#define AC_MSETH_IND 0x08 +#define AC_AREF_IND 0x09 +#define AC_BDRLSB_IND 0x0A +#define AC_BDRMID_IND 0x0B +#define AC_BDRMSB_IND 0x0C +#define AC_BDRINV_IND 0x0D +#define AC_GAIN_IND 0x0E +#define AC_TEST_IND 0x0F +#define AC_RSCONF_IND 0x10 +#define AC_SYNC_IND 0x11 +#define AC_POLA1_IND 0x12 +#define AC_CPTUNCOR_IND 0x13 +#define AC_BERLSB_IND 0x14 +#define AC_BERMID_IND 0x15 +#define AC_BERMSB_IND 0x16 +#define AC_VAGC1_IND 0x17 +#define AC_MSE_IND 0x18 +#define AC_VAFC_IND 0x19 +#define AC_IDENTITY_IND 0x1A +#define AC_ADC_IND 0x1B +#define AC_EQCONF2_IND 0x1C +#define AC_CKOFFSET_IND 0x1D + +#define AC_INTP_IND 0x20 +#define AC_SATNYQ_IND 0x21 +#define AC_SATADC_IND 0x22 +#define AC_HALFADC_IND 0x23 +#define AC_SATDEC1_IND 0x24 +#define AC_SATDEC2_IND 0x25 +#define AC_SATDEC3_IND 0x26 +#define AC_SATAAF_IND 0x27 +#define AC_MDIV_IND 0x28 +#define AC_NDIV_IND 0x29 +#define AC_PLL_IND 0x2A +#define AC_POLA2_IND 0x2B +#define AC_CONTROL_IND 0x2C +#define AC_SWEEP_IND 0x2D +#define AC_AGCCONF2_IND 0x2E +#define AC_VAGC2_IND 0x2F +#define AC_SATTHR_IND 0x30 +#define AC_HALFTHR_IND 0x31 +#define AC_ITSEL_IND 0x32 +#define AC_ITSTAT_IND 0x33 +#define AC_PWMREF_IND 0x34 +#define AC_TUNMAX_IND 0x35 +#define AC_TUNMIN_IND 0x36 +#define AC_DELTAF1_IND 0x37 +#define AC_DELTAF2_IND 0x38 +#define AC_CONSTI_IND 0x39 +#define AC_CONSTQ_IND 0x3A +#define AC_IFMAX_IND 0x3B +#define AC_IFMIN_IND 0x3C + +#define AC_REQCO_IND 0x40 +#define AC_REQCO_CENTRALCOEF_IND 0x50 + +#define AC_IEQCO_IND 0x80 +#define AC_IEQCO_CENTRALCOEF_IND 0x90 + +/* DEFAULT VALUES */ +#define AC_ADC_SW_DEF 0x30 +#define AC_CARCONFHIGHSR_DEF 0x02 +#define AC_CARCONFLOWSR_DEF 0x0A +#define AC_CARCONFVERYLOWSR_DEF 0x05 +#define AC_CARCONFALGO_DEF 0x0C +#define AC_PWMREF_DEF 0x80 +#define AC_INTP_DEF 0x00 +#define AC_SWEEP_DEF 0x80 + +/* DEFINE VALUES */ +#define AC_NOSI_VAL 0 +#define AC_YESSI_VAL 1 +#define AC_AUTOSI_VAL 2 + +#define AC_PHILIPS_VAL 0 +#define AC_PHILIPSLHI_VAL 1 +#define AC_SONY_VAL 2 +#define AC_NOTUNER_VAL 3 + +#define AC_16QAM_VAL 0 +#define AC_32QAM_VAL 1 +#define AC_64QAM_VAL 2 +#define AC_128QAM_VAL 3 +#define AC_256QAM_VAL 4 +#define AC_4QAM_VAL 5 + +#define AC_AUTOQAM_VAL 2 +#define AC_FREF_VAL62500 62500L +#define AC_FREF_VAL 78125 + +#define AC_PHILIPSLOW_VAL 0xA1 +#define AC_PHILIPSMID_VAL 0x92 +#define AC_PHILIPSHIGH_VAL 0x34 + +#define AC_PHILIPSLHILOW_VAL 0x06 +#define AC_PHILIPSLHIMID_VAL 0x05 +#define AC_PHILIPSLHIHIGH_VAL 0x03 + +#define AC_VHF1_SONY_VAL 0x01 +#define AC_VHF3_SONY_VAL 0x02 +#define AC_UHF_SONY_VAL 0x04 + +#define AC_BER_DEPTH5_VAL 0x00 +#define AC_BER_DEPTH6_VAL 0x40 +#define AC_BER_DEPTH7_VAL 0x80 +#define AC_BER_DEPTH8_VAL 0xC0 + +#define AC_VERYFASTAGCCONV_VAL 0 +#define AC_FASTAGCCONV_VAL 1 +#define AC_MIDAGCCONV_VAL 2 +#define AC_SLOWAGCCONV_VAL 3 + +#define AC_ALGOAGCTIMER_VAL 100000 +#define AC_ALGOGAINTIMER_VAL 10000 +#define AC_ALGOSITIMER_VAL 30000 +#define AC_ALGOLOCKTIMER_VAL 200000 +#define AC_ALGOLOCKCARRIER_VAL 265533 // 2*SWDYN/SWSTEP*SWLENGTH + +#define AC_COEFTRESHOLD_VAL 490000 //562500 + +#define AC_ALGOGAINMAX_VAL 5 +#define AC_ALGOGAINMIN_VAL 0 +#define AC_ALGOGAINSCANMIN_VAL 0 +#define AC_ALGOGAINSCANMID_VAL 2 +#define AC_ALGOGAINSCANMAX_VAL 4 + +#define AC_DVB_ROLLOFF_VAL 115 +#define AC_SCANSTEP_VAL 47 +#define AC_FREQSTEP_VAL 62 + +/* DEFINE MASKS */ +#define AC_EQCONF1_POSI_MSK 0x70 +#define AC_EQCONF1_ENEQUAL_MSK 0x02 +#define AC_ADC_SW_MSK 0x30 +#define AC_GAIN_SFIL_MSK 0x10 +#define AC_CLKCONF_NDEC_MSK 0xC0 +#define AC_CARCONF_MSK 0x3F +#define AC_CONF_QAM_MSK 0x1C +#define AC_RSCONF_PVBER_MSK 0xC0 +#define AC_CPTUNCOR_CPTU_MSK 0x7F +#define AC_GAIN_GNYQ_MSK 0xE0 +#define AC_AGCCONF1_KAGC_MSK 0x03 +#define AC_GAIN_SSAT_MSK 0x03 +#define AC_SYNC_BER_MSK 0x30 +#define AC_DEMODSTAT_FEL_MSK 0x08 +#define AC_DEMODSTAT_UNCOR_MSK 0x80 + + +/* DEFINE BITS */ +#define AC_CONF_CLB_BIT 0x01 +#define AC_AGCCONF1_POSAGC_BIT 0x20 +#define AC_AGCCONF2_ENAGC2_BIT 0x08 +#define AC_ADC_PCLK_BIT 0x01 +#define AC_TEST_BYPIIC_BIT 0x80 +#define AC_EQCONF_ENEQUAL_BIT 0x02 +#define AC_CONF_INVIQ_BIT 0x20 +#define AC_RSCONF_CLBUNC_BIT 0x20 +#define AC_CLKCONF_DYN_BIT 0x08 +#define AC_SYNC_NODVB_BIT 0x40 +#define AC_CLKCONF_GAIN3_BIT 0x10 +#define AC_AGCCONF1_PPWM1_BIT 0x04 +#define AC_AGCCONF2_PPWM2_BIT 0x02 +#define AC_PLL_BYPPLL_BIT 0x10 +#define AC_POLA1_POCLK1_BIT 0x01 +#define AC_POLA2_POCLK2_BIT 0x01 +#define AC_POLA2_MSBFIRST2_BIT 0x40 +#define AC_EQCONF1_DFE_BIT 0x01 +#define AC_EQCONF1_ENEQUAL_BIT 0x02 +#define AC_EQCONF2_SGNALGO_BIT 0x20 +#define AC_EQCONF2_CTADAPT_BIT 0x08 +#define AC_DELTAF2_ALGOD_BIT 0x04 +#define AC_INTP_INTSEL_BIT 0x01 +#define AC_INTP_MSBFIRST_BIT 0x02 +#define AC_INTP_PARMOD_BIT 0x08 +#define AC_EQCONF1_ENADAPT_BIT 0x04 +#define AC_SYNC_CARLOCK_BIT 0x02 +#define AC_SYNC_FSYNC_BIT 0x04 +#define AC_SYNC_FEL_BIT 0x08 + +/* DEFINE RETURN VALUES */ +#define AC_SUCCESS_RET 0 +#define AC_FAILED_RET 1 +#define AC_NOT_FINISHED_RET 2 +#define AC_NO_ERROR_RET 0 + +#endif //__CU1216_REGS_H diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/frontends/Kconfig linux-2.6.23.1.mantis/drivers/media/dvb/frontends/Kconfig --- linux-2.6.23.1/drivers/media/dvb/frontends/Kconfig 2007-10-12 18:43:44.000000000 +0200 +++ linux-2.6.23.1.mantis/drivers/media/dvb/frontends/Kconfig 2007-10-15 12:45:08.000000000 +0200 @@ -71,6 +71,20 @@ config DVB_TDA10086 help A DVB-S tuner module. Say Y when you want to support this frontend. +config DVB_MB86A16 + tristate "Fujitsu MB86A16 based" + depends on DVB_CORE && I2C + default m + help + A DVB-S/DSS tuner module. Say Y when you want to support this frontend. + +config DVB_CU1216 + tristate "Philips CU1216 tuner based" + depends on DVB_CORE && I2C + default m + help + A DVB-C tuner module. Say Y when you want to support this frontend. + comment "DVB-T (terrestrial) frontends" depends on DVB_CORE diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/frontends/Makefile linux-2.6.23.1.mantis/drivers/media/dvb/frontends/Makefile --- linux-2.6.23.1/drivers/media/dvb/frontends/Makefile 2007-10-12 18:43:44.000000000 +0200 +++ linux-2.6.23.1.mantis/drivers/media/dvb/frontends/Makefile 2007-10-15 12:45:24.000000000 +0200 @@ -42,3 +42,5 @@ obj-$(CONFIG_DVB_TDA827X) += tda827x.o obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o obj-$(CONFIG_DVB_TUNER_QT1010) += qt1010.o obj-$(CONFIG_DVB_TUA6100) += tua6100.o +obj-$(CONFIG_DVB_MB86A16) += mb86a16.o +obj-$(CONFIG_DVB_CU1216) += cu1216.o diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/frontends/mb86a16.c linux-2.6.23.1.mantis/drivers/media/dvb/frontends/mb86a16.c --- linux-2.6.23.1/drivers/media/dvb/frontends/mb86a16.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23.1.mantis/drivers/media/dvb/frontends/mb86a16.c 2007-10-10 17:51:19.000000000 +0200 @@ -0,0 +1,1930 @@ +/* + Fujitsu MB86A16 DVB-S/DSS DC Receiver driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include + +#include "dvb_frontend.h" +#include "mb86a16.h" +#include "mb86a16_priv.h" + +unsigned int verbose = 5; +module_param(verbose, int, 0644); + +#define ABS(x) ((x) < 0 ? (-x) : (x)) + +struct mb86a16_state { + struct i2c_adapter *i2c_adap; + const struct mb86a16_config *config; + struct dvb_frontend frontend; + + // tuning parameters + int frequency; + int srate; + + // Internal stuff + int master_clk; + int deci; + int csel; + int rsel; +}; + +#define MB86A16_ERROR 0 +#define MB86A16_NOTICE 1 +#define MB86A16_INFO 2 +#define MB86A16_DEBUG 3 + +#define dprintk(x, y, z, format, arg...) do { \ + if (z) { \ + if ((x > MB86A16_ERROR) && (x > y)) \ + printk(KERN_ERR "%s: " format "\n", __func__, ##arg); \ + else if ((x > MB86A16_NOTICE) && (x > y)) \ + printk(KERN_NOTICE "%s: " format "\n", __func__, ##arg); \ + else if ((x > MB86A16_INFO) && (x > y)) \ + printk(KERN_INFO "%s: " format "\n", __func__, ##arg); \ + else if ((x > MB86A16_DEBUG) && (x > y)) \ + printk(KERN_DEBUG "%s: " format "\n", __func__, ##arg); \ + } else { \ + if (x > y) \ + printk(format, ##arg); \ + } \ +} while (0) + +#define TRACE_IN dprintk(verbose, MB86A16_DEBUG, 1, "-->()") +#define TRACE_OUT dprintk(verbose, MB86A16_DEBUG, 1, "()-->") + +static int mb86a16_write(struct mb86a16_state *state, u8 reg, u8 val) +{ + int ret; + u8 buf[] = { reg, val }; + + struct i2c_msg msg = { + .addr = state->config->demod_address, + .flags = 0, + .buf = buf, + .len = 2 + }; + + dprintk(verbose, MB86A16_DEBUG, 1, + "writing to [0x%02x],Reg[0x%02x],Data[0x%02x]", + state->config->demod_address, buf[0], buf[1]); + + ret = i2c_transfer(state->i2c_adap, &msg, 1); + + return (ret != 1) ? -EREMOTEIO : 0; +} + +static int mb86a16_read(struct mb86a16_state *state, u8 reg, u8 *val) +{ + int ret; + u8 b0[] = { reg }; + u8 b1[] = { 0 }; + + struct i2c_msg msg[] = { + { + .addr = state->config->demod_address, + .flags = 0, + .buf = b0, + .len = 1 + },{ + .addr = state->config->demod_address, + .flags = I2C_M_RD, + .buf = b1, + .len = 1 + } + }; + ret = i2c_transfer(state->i2c_adap, msg, 2); + if (ret != 2) { + dprintk(verbose, MB86A16_ERROR, 1, "read error(reg=0x%02x, ret=0x%i)", + reg, ret); + + return -EREMOTEIO; + } + *val = b1[0]; + + return ret; +} + +static int CNTM_set(struct mb86a16_state *state, + unsigned char timint1, + unsigned char timint2, + unsigned char cnext) +{ + unsigned char val; + + val = (timint1 << 4) | (timint2 << 2) | cnext; + if (mb86a16_write(state, MB86A16_CNTMR, val) < 0) + goto err; + + return 0; + +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int smrt_set(struct mb86a16_state *state, int rate) +{ + int tmp ; + int m ; + unsigned char STOFS0, STOFS1; + + m = 1 << state->deci; + tmp = (8192 * state->master_clk - 2 * m * rate * 8192 + state->master_clk / 2) / state->master_clk; + + STOFS0 = tmp & 0x0ff; + STOFS1 = (tmp & 0xf00) >> 8; + + if (mb86a16_write(state, MB86A16_SRATE1, (state->deci << 2) | + (state->csel << 1) | + state->rsel) < 0) + goto err; + if (mb86a16_write(state, MB86A16_SRATE2, STOFS0) < 0) + goto err; + if (mb86a16_write(state, MB86A16_SRATE3, STOFS1) < 0) + goto err; + + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -1; +} + +static int srst(struct mb86a16_state *state) +{ + if (mb86a16_write(state, MB86A16_RESET, 0x04) < 0) + goto err; + + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + +} + +static int afcex_data_set(struct mb86a16_state *state, + unsigned char AFCEX_L, + unsigned char AFCEX_H) +{ + if (mb86a16_write(state, MB86A16_AFCEXL, AFCEX_L) < 0) + goto err; + if (mb86a16_write(state, MB86A16_AFCEXH, AFCEX_H) < 0) + goto err; + + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + + return -1; +} + +static int afcofs_data_set(struct mb86a16_state *state, + unsigned char AFCEX_L, + unsigned char AFCEX_H) +{ + if (mb86a16_write(state, 0x58, AFCEX_L) < 0) + goto err; + if (mb86a16_write(state, 0x59, AFCEX_H) < 0) + goto err; + + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int stlp_set(struct mb86a16_state *state, + unsigned char STRAS, + unsigned char STRBS) +{ + if (mb86a16_write(state, MB86A16_STRFILTCOEF1, (STRBS << 3) | (STRAS)) < 0) + goto err; + + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int Vi_set(struct mb86a16_state *state, unsigned char ETH, unsigned char VIA) +{ + if (mb86a16_write(state, MB86A16_VISET2, 0x04) < 0) + goto err; + if (mb86a16_write(state, MB86A16_VISET3, 0xf5) < 0) + goto err; + + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int initial_set(struct mb86a16_state *state) +{ + if (stlp_set(state, 5, 7)) + goto err; + + udelay(100); + if (afcex_data_set(state, 0, 0)) + goto err; + + udelay(100); + if (afcofs_data_set(state, 0, 0)) + goto err; + + udelay(100); + if (mb86a16_write(state, MB86A16_CRLFILTCOEF1, 0x16) < 0) + goto err; + if (mb86a16_write(state, 0x2f, 0x21) < 0) + goto err; + if (mb86a16_write(state, MB86A16_VIMAG, 0x38) < 0) + goto err; + if (mb86a16_write(state, MB86A16_FAGCS1, 0x00) < 0) + goto err; + if (mb86a16_write(state, MB86A16_FAGCS2, 0x1c) < 0) + goto err; + if (mb86a16_write(state, MB86A16_FAGCS3, 0x20) < 0) + goto err; + if (mb86a16_write(state, MB86A16_FAGCS4, 0x1e) < 0) + goto err; + if (mb86a16_write(state, MB86A16_FAGCS5, 0x23) < 0) + goto err; + if (mb86a16_write(state, 0x54, 0xff) < 0) + goto err; + if (mb86a16_write(state, MB86A16_TSOUT, 0x00) < 0) + goto err; + + return 0; + +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int S01T_set(struct mb86a16_state *state, + unsigned char s1t, + unsigned s0t) +{ + if (mb86a16_write(state, 0x33, (s1t << 3) | s0t) < 0) + goto err; + + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +#if 0 + +static int S23T_set(struct mb86a16_state *state, + int sr, + unsigned char SIG, + unsigned char *S2T, + unsigned char *S3T) +{ + //changed begin + if (sr >= 22501) { + if (SIG > 115) { + *S2T = 4; *S3T = 4; + } else if (SIG > 90) { + *S2T = 5; *S3T = 4; + } else if (SIG > 80) { + *S2T = 6; *S3T = 4; + } else if (SIG > 70) { + *S2T = 7; *S3T = 4; + } else if (SIG > 60) { + *S2T = 8; *S3T = 5; + } else if (SIG > 50) { + *S2T = 9; *S3T = 6; + } else { + *S2T = 9; *S3T = 7; + } + } else if (sr >= 11251) { + if ( SIG > 90 ) { + *S2T = 4; *S3T = 4; + } else if (SIG > 70 ) { + *S2T = 5; *S3T = 4; + } else if (SIG > 60) { + *S2T = 6; *S3T = 4; + } else if ( SIG > 50 ) { + *S2T = 7; *S3T = 5; + } else { + *S2T = 8; *S3T = 6; + } + } else { + if ( SIG > 90) { + *S2T = 4; *S3T = 4; + } else if (SIG > 50) { + *S2T = 5; *S3T = 5; + } else { + *S2T = 6; *S3T = 6; + } + } + //changed end + + if (mb86a16_write(state, 0x34, (*S3T << 4) | (*S2T)) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + return 0; +} + +#endif + +static int EN_set(struct mb86a16_state *state, + int cren, + int afcen) +{ + unsigned char val; + + val = 0x7a | (cren << 7) | (afcen << 2); + if (mb86a16_write(state, 0x49, val) < 0) + goto err; + + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int AFCEXEN_set(struct mb86a16_state *state, + int afcexen, + int smrt) +{ + unsigned char AFCA ; + + if (smrt > 18875) + AFCA = 4; + else if (smrt > 9375) + AFCA = 3; + else if (smrt > 2250) + AFCA = 2; + else + AFCA = 1; + + if (mb86a16_write(state, 0x2a, 0x02 | (afcexen << 5) | (AFCA << 2)) < 0) + goto err; + + return 0; + +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int DAGC_data_set(struct mb86a16_state *state, + unsigned char DAGCA, + unsigned char DAGCW) +{ + if (mb86a16_write(state, 0x2d, (DAGCA << 3) | DAGCW) < 0) + goto err; + + return 0; + +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static void smrt_info_get(struct mb86a16_state *state, int rate) +{ + if (rate >= 37501) { + state->deci = 0; state->csel = 0; state->rsel = 0; + } else if (rate >= 30001) { + state->deci = 0; state->csel = 0; state->rsel = 1; + } else if (rate >= 26251) { + state->deci = 0; state->csel = 1; state->rsel = 0; + } else if (rate >= 22501) { + state->deci = 0; state->csel = 1; state->rsel = 1; + } else if (rate >= 18751) { + state->deci = 1; state->csel = 0; state->rsel = 0; + } else if (rate >= 15001) { + state->deci = 1; state->csel = 0; state->rsel = 1; + } else if (rate >= 13126) { + state->deci = 1; state->csel = 1; state->rsel = 0; + } else if (rate >= 11251) { + state->deci = 1; state->csel = 1; state->rsel = 1; + } else if (rate >= 9376) { + state->deci = 2; state->csel = 0; state->rsel = 0; + } else if (rate >= 7501) { + state->deci = 2; state->csel = 0; state->rsel = 1; + } else if (rate >= 6563) { + state->deci = 2; state->csel = 1; state->rsel = 0; + } else if (rate >= 5626) { + state->deci = 2; state->csel = 1; state->rsel = 1; + } else if (rate >= 4688) { + state->deci = 3; state->csel = 0; state->rsel = 0; + } else if (rate >= 3751) { + state->deci = 3; state->csel = 0; state->rsel = 1; + } else if (rate >= 3282) { + state->deci = 3; state->csel = 1; state->rsel = 0; + } else if (rate >= 2814) { + state->deci = 3; state->csel = 1; state->rsel = 1; + } else if (rate >= 2344) { + state->deci = 4; state->csel = 0; state->rsel = 0; + } else if (rate >= 1876) { + state->deci = 4; state->csel = 0; state->rsel = 1; + } else if (rate >= 1641) { + state->deci = 4; state->csel = 1; state->rsel = 0; + } else if (rate >= 1407) { + state->deci = 4; state->csel = 1; state->rsel = 1; + } else if (rate >= 1172) { + state->deci = 5; state->csel = 0; state->rsel = 0; + } else if (rate >= 939) { + state->deci = 5; state->csel = 0; state->rsel = 1; + } else if (rate >= 821) { + state->deci = 5; state->csel = 1; state->rsel = 0; + } else { + state->deci = 5; state->csel = 1; state->rsel = 1; + } + + if (state->csel == 0) + state->master_clk = 92000; + else + state->master_clk = 61333; + +} + +static int signal_det(struct mb86a16_state *state, + int smrt, + unsigned char *SIG) +{ + + int ret ; + int smrtd ; + int wait_sym ; + + u32 wait_t; + unsigned char S[3] ; + int i ; + + if (*SIG > 45) { + if (CNTM_set(state, 2, 1, 2) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "CNTM set Error"); + return -1; + } + wait_sym = 40000; + } else { + if (CNTM_set(state, 3, 1, 2) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "CNTM set Error"); + return -1; + } + wait_sym = 80000; + } + for (i = 0; i < 3; i++) { + if (i == 0 ) + smrtd = smrt * 98 / 100; + else if (i == 1) + smrtd = smrt; + else + smrtd = smrt * 102 / 100; + smrt_info_get(state, smrtd); + smrt_set(state, smrtd); + srst(state); + wait_t = (wait_sym + 99 * smrtd / 100) / smrtd; + if (wait_t == 0) + wait_t = 1; + msleep_interruptible(10); + if (mb86a16_read(state, 0x37, &(S[i])) != 2) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + } + if ((S[1] > S[0] * 112 / 100) && + (S[1] > S[2] * 112 / 100)) { + + ret = 1; + } else { + ret = 0; + } + *SIG = S[1]; + + if (CNTM_set(state, 0, 1, 2) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "CNTM set Error"); + return -1; + } + + return ret; +} + +static int rf_val_set(struct mb86a16_state *state, + int f, + int smrt, + unsigned char R) +{ + unsigned char C, F, B; + int M; + unsigned char rf_val[5]; + int ack = -1; + + if (smrt > 37750 ) + C = 1; + else if (smrt > 18875) + C = 2; + else if (smrt > 5500 ) + C = 3; + else + C = 4; + + if (smrt > 30500) + F = 3; + else if (smrt > 9375) + F = 1; + else if (smrt > 4625) + F = 0; + else + F = 2; + + if (f < 1060) + B = 0; + else if (f < 1175) + B = 1; + else if (f < 1305) + B = 2; + else if (f < 1435) + B = 3; + else if (f < 1570) + B = 4; + else if (f < 1715) + B = 5; + else if (f < 1845) + B = 6; + else if (f < 1980) + B = 7; + else if (f < 2080) + B = 8; + else + B = 9; + + M = f * (1 << R) / 2; + + rf_val[0] = 0x01 | (C << 3) | (F << 1); + rf_val[1] = (R << 5) | ((M & 0x1f000) >> 12); + rf_val[2] = (M & 0x00ff0) >> 4; + rf_val[3] = ((M & 0x0000f) << 4) | B; + + // Frequency Set + if (mb86a16_write(state, 0x21, rf_val[0]) < 0) + ack = 0; + if (mb86a16_write(state, 0x22, rf_val[1]) < 0) + ack = 0; + if (mb86a16_write(state, 0x23, rf_val[2]) < 0) + ack = 0; + if (mb86a16_write(state, 0x24, rf_val[3]) < 0) + ack = 0; + if (mb86a16_write(state, 0x25, 0x01) < 0) + ack = 0; + if (ack == 0) { + dprintk(verbose, MB86A16_ERROR, 1, "RF Setup - I2C transfer error"); + return -EREMOTEIO; + } + + return 0; +} + +static int afcerr_chk(struct mb86a16_state *state) +{ + unsigned char AFCM_L, AFCM_H ; + int AFCM ; + int afcm, afcerr ; + + if (mb86a16_read(state, 0x0e, &AFCM_L) != 2) + goto err; + if (mb86a16_read(state, 0x0f, &AFCM_H) != 2) + goto err; + + AFCM = (AFCM_H << 8) + AFCM_L; + + if (AFCM > 2048) + afcm = AFCM - 4096; + else + afcm = AFCM; + afcerr = afcm * state->master_clk / 8192; + + return afcerr; + +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int dagcm_val_get(struct mb86a16_state *state) +{ + int DAGCM; + unsigned char DAGCM_H, DAGCM_L; + + if (mb86a16_read(state, 0x45, &DAGCM_L) != 2) + goto err; + if (mb86a16_read(state, 0x46, &DAGCM_H) != 2) + goto err; + + DAGCM = (DAGCM_H << 8) + DAGCM_L; + + return DAGCM; + +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int mb86a16_read_status(struct dvb_frontend *fe, fe_status_t *status) +{ + u8 stat, stat2; + struct mb86a16_state *state = fe->demodulator_priv; + + *status = 0; + + if (mb86a16_read(state, MB86A16_SIG1, &stat) != 2) + goto err; + if (mb86a16_read(state, MB86A16_SIG2, &stat2) != 2) + goto err; + if ((stat > 25) && (stat2 > 25)) + *status |= FE_HAS_SIGNAL; + if ((stat > 45) && (stat2 > 45)) + *status |= FE_HAS_CARRIER; + + if (mb86a16_read(state, MB86A16_STATUS, &stat) != 2) + goto err; + + if (stat & 0x01) + *status |= FE_HAS_SYNC; + if (stat & 0x01) + *status |= FE_HAS_VITERBI; + + if (mb86a16_read(state, MB86A16_FRAMESYNC, &stat) != 2) + goto err; + + if ((stat & 0x0f) && (*status & FE_HAS_VITERBI)) + *status |= FE_HAS_LOCK; + + return 0; + +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int sync_chk(struct mb86a16_state *state, + unsigned char *VIRM) +{ + unsigned char val; + int sync; + + if (mb86a16_read(state, 0x0d, &val) != 2) + goto err; + + dprintk(verbose, MB86A16_INFO, 1, "Status = %02x,", val); + sync = val & 0x01; + *VIRM = (val & 0x1c) >> 2; + + return sync; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + +} + +static int freqerr_chk(struct mb86a16_state *state, + int fTP, + int smrt, + int unit) +{ + unsigned char CRM, AFCML, AFCMH; + unsigned char temp1, temp2, temp3; + int crm, afcm, AFCM; + int crrerr, afcerr; // [kHz] + int frqerr; // [MHz] + int afcen, afcexen = 0; + int R, M, fOSC, fOSC_OFS; + + if (mb86a16_read(state, 0x43, &CRM) != 2) + goto err; + + if (CRM > 127) + crm = CRM - 256; + else + crm = CRM; + + crrerr = smrt * crm / 256; + if (mb86a16_read(state, 0x49, &temp1) != 2) + goto err; + + afcen = (temp1 & 0x04) >> 2; + if (afcen == 0) { + if (mb86a16_read(state, 0x2a, &temp1) != 2) + goto err; + afcexen = (temp1 & 0x20) >> 5; + } + + if (afcen == 1) { + if (mb86a16_read(state, 0x0e, &AFCML) != 2) + goto err; + if (mb86a16_read(state, 0x0f, &AFCMH) != 2) + goto err; + } else if (afcexen == 1) { + if (mb86a16_read(state, 0x2b, &AFCML) != 2) + goto err; + if (mb86a16_read(state, 0x2c, &AFCMH) != 2) + goto err; + } + if ((afcen == 1) || (afcexen == 1)) { + smrt_info_get(state, smrt); + AFCM = ((AFCMH & 0x01) << 8) + AFCML; + if (AFCM > 255) + afcm = AFCM - 512; + else + afcm = AFCM; + + afcerr = afcm * state->master_clk / 8192; + } else + afcerr = 0; + + if (mb86a16_read(state, 0x22, &temp1) != 2) + goto err; + if (mb86a16_read(state, 0x23, &temp2) != 2) + goto err; + if (mb86a16_read(state, 0x24, &temp3) != 2) + goto err; + + R = (temp1 & 0xe0) >> 5; + M = ((temp1 & 0x1f) << 12) + (temp2 << 4) + (temp3 >> 4); + if (R == 0) + fOSC = 2 * M; + else + fOSC = M; + + fOSC_OFS = fOSC - fTP; + + if (unit == 0) { //[MHz] + if (crrerr + afcerr + fOSC_OFS * 1000 >= 0) + frqerr = (crrerr + afcerr + fOSC_OFS * 1000 + 500) / 1000; + else + frqerr = (crrerr + afcerr + fOSC_OFS * 1000 - 500) / 1000; + } else { //[kHz] + frqerr = crrerr + afcerr + fOSC_OFS * 1000; + } + + return frqerr; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static unsigned char vco_dev_get(struct mb86a16_state *state, int smrt) +{ + unsigned char R; + + if (smrt > 9375) + R = 0; + else + R = 1; + + return R; +} + +static void swp_info_get(struct mb86a16_state *state, + int fOSC_start, + int smrt, + int v, int R, + int swp_ofs, + int *fOSC, + int *afcex_freq, + unsigned char *AFCEX_L, + unsigned char *AFCEX_H) +{ + int AFCEX ; + int crnt_swp_freq ; + + crnt_swp_freq = fOSC_start * 1000 + v * swp_ofs; + + if (R == 0 ) + *fOSC = (crnt_swp_freq + 1000) / 2000 * 2; + else + *fOSC = (crnt_swp_freq + 500) / 1000; + + if (*fOSC >= crnt_swp_freq) + *afcex_freq = *fOSC *1000 - crnt_swp_freq; + else + *afcex_freq = crnt_swp_freq - *fOSC * 1000; + + AFCEX = *afcex_freq * 8192 / state->master_clk; + *AFCEX_L = AFCEX & 0x00ff; + *AFCEX_H = (AFCEX & 0x0f00) >> 8; +} + + +static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V, int vmax, int vmin, + int SIGMIN, int fOSC, int afcex_freq, int swp_ofs, unsigned char *SIG1) +{ + int swp_freq ; + + if ((i % 2 == 1) && (v <= vmax)) { + // positive v (case 1) + if ((v - 1 == vmin) && + (*(V + 30 + v) >= 0) && + (*(V + 30 + v - 1) >= 0) && + (*(V + 30 + v - 1) > *(V + 30 + v)) && + (*(V + 30 + v - 1) > SIGMIN)) { + + swp_freq = fOSC * 1000 + afcex_freq - swp_ofs; + *SIG1 = *(V + 30 + v - 1); + } else if ((v == vmax) && + (*(V + 30 + v) >= 0) && + (*(V + 30 + v - 1) >= 0) && + (*(V + 30 + v) > *(V + 30 + v - 1)) && + (*(V + 30 + v) > SIGMIN)) { + // (case 2) + swp_freq = fOSC * 1000 + afcex_freq; + *SIG1 = *(V + 30 + v); + } else if ((*(V + 30 + v) > 0) && + (*(V + 30 + v - 1) > 0) && + (*(V + 30 + v - 2) > 0) && + (*(V + 30 + v - 3) > 0) && + (*(V + 30 + v - 1) > *(V + 30 + v)) && + (*(V + 30 + v - 2) > *(V + 30 + v - 3)) && + ((*(V + 30 + v - 1) > SIGMIN) || + (*(V + 30 + v - 2) > SIGMIN))) { + // (case 3) + if (*(V + 30 + v - 1) >= *(V + 30 + v - 2)) { + swp_freq = fOSC * 1000 + afcex_freq - swp_ofs; + *SIG1 = *(V + 30 + v - 1); + } else { + swp_freq = fOSC * 1000 + afcex_freq - swp_ofs * 2; + *SIG1 = *(V + 30 + v - 2); + } + } else if ((v == vmax) && + (*(V + 30 + v) >= 0) && + (*(V + 30 + v - 1) >= 0) && + (*(V + 30 + v - 2) >= 0) && + (*(V + 30 + v) > *(V + 30 + v - 2)) && + (*(V + 30 + v - 1) > *(V + 30 + v - 2)) && + ((*(V + 30 + v) > SIGMIN) || + (*(V + 30 + v - 1) > SIGMIN))) { + // (case 4) + if (*(V + 30 + v) >= *(V + 30 + v - 1)) { + swp_freq = fOSC * 1000 + afcex_freq; + *SIG1 = *(V + 30 + v); + } else { + swp_freq = fOSC * 1000 + afcex_freq - swp_ofs; + *SIG1 = *(V + 30 + v - 1); + } + } else { + swp_freq = -1 ; + } + } else if ((i % 2 == 0) && (v >= vmin)) { + // Negative v (case 1) + if ((*(V + 30 + v) > 0) && + (*(V + 30 + v + 1) > 0) && + (*(V + 30 + v + 2) > 0) && + (*(V + 30 + v + 1) > *(V + 30 + v)) && + (*(V + 30 + v + 1) > *(V + 30 + v + 2)) && + (*(V + 30 + v + 1) > SIGMIN)) { + + swp_freq = fOSC * 1000 + afcex_freq + swp_ofs; + *SIG1 = *(V + 30 + v + 1); + } else if ((v + 1 == vmax) && + (*(V + 30 + v) >= 0) && + (*(V + 30 + v + 1) >= 0) && + (*(V + 30 + v + 1) > *(V + 30 + v)) && + (*(V + 30 + v + 1) > SIGMIN)) { + // (case 2) + swp_freq = fOSC * 1000 + afcex_freq + swp_ofs; + *SIG1 = *(V + 30 + v); + } else if ((v == vmin) && + (*(V + 30 + v) > 0) && + (*(V + 30 + v + 1) > 0) && + (*(V + 30 + v + 2) > 0) && + (*(V + 30 + v) > *(V + 30 + v + 1)) && + (*(V + 30 + v) > *(V + 30 + v + 2)) && + (*(V + 30 + v) > SIGMIN)) { + // (case 3) + swp_freq = fOSC * 1000 + afcex_freq; + *SIG1 = *(V + 30 + v); + } else if ((*(V + 30 + v) >= 0) && + (*(V + 30 + v + 1) >= 0) && + (*(V + 30 + v + 2) >= 0) && + (*(V +30 + v + 3) >= 0) && + (*(V + 30 + v + 1) > *(V + 30 + v)) && + (*(V + 30 + v + 2) > *(V + 30 + v + 3)) && + ((*(V + 30 + v + 1) > SIGMIN) || + (*(V + 30 + v + 2) > SIGMIN))) { + // (case 4) + if (*(V + 30 + v + 1) >= *(V + 30 + v + 2)) { + swp_freq = fOSC * 1000 + afcex_freq + swp_ofs; + *SIG1 = *(V + 30 + v + 1); + } else { + swp_freq = fOSC * 1000 + afcex_freq + swp_ofs * 2; + *SIG1 = *(V + 30 + v + 2); + } + } else if ((*(V + 30 + v) >= 0) && + (*(V + 30 + v + 1) >= 0) && + (*(V + 30 + v + 2) >= 0) && + (*(V + 30 + v + 3) >= 0) && + (*(V + 30 + v) > *(V + 30 + v + 2)) && + (*(V + 30 + v + 1) > *(V + 30 + v + 2)) && + (*(V + 30 + v) > *(V + 30 + v + 3)) && + (*(V + 30 + v + 1) > *(V + 30 + v + 3)) && + ((*(V + 30 + v) > SIGMIN) || + (*(V + 30 + v + 1) > SIGMIN))) { + // (case 5) + if (*(V + 30 + v) >= *(V + 30 + v + 1)) { + swp_freq = fOSC * 1000 + afcex_freq; + *SIG1 = *(V + 30 + v); + } else { + swp_freq = fOSC * 1000 + afcex_freq + swp_ofs; + *SIG1 = *(V + 30 + v + 1); + } + } else if ((v + 2 == vmin) && + (*(V + 30 + v) >= 0) && + (*(V + 30 + v + 1) >= 0) && + (*(V + 30 + v + 2) >= 0) && + (*(V + 30 + v + 1) > *(V + 30 + v)) && + (*(V + 30 + v + 2) > *(V + 30 + v)) && + ((*(V + 30 + v + 1) > SIGMIN) || + (*(V + 30 + v + 2) > SIGMIN))) { + // (case 6) + if (*(V + 30 + v + 1) >= *(V + 30 + v + 2)) { + swp_freq = fOSC * 1000 + afcex_freq + swp_ofs; + *SIG1 = *(V + 30 + v + 1); + } else { + swp_freq = fOSC * 1000 + afcex_freq + swp_ofs * 2; + *SIG1 = *(V + 30 + v + 2); + } + } else if ((vmax == 0) && (vmin == 0) && (*(V + 30 + v) > SIGMIN)) { + swp_freq = fOSC * 1000; + *SIG1 = *(V + 30 + v); + } else swp_freq = -1; + } else swp_freq = -1; + + return swp_freq; +} + +static void swp_info_get2(struct mb86a16_state *state, + int smrt, + int R, + int swp_freq, + int *afcex_freq, + int *fOSC, + unsigned char *AFCEX_L, + unsigned char *AFCEX_H) +{ + int AFCEX ; + + if (R == 0) + *fOSC = (swp_freq + 1000) / 2000 * 2; + else + *fOSC = (swp_freq + 500) / 1000; + + if (*fOSC >= swp_freq) + *afcex_freq = *fOSC * 1000 - swp_freq; + else + *afcex_freq = swp_freq - *fOSC * 1000; + + AFCEX = *afcex_freq * 8192 / state->master_clk; + *AFCEX_L = AFCEX & 0x00ff; + *AFCEX_H = (AFCEX & 0x0f00) >> 8; +} + +static void afcex_info_get(struct mb86a16_state *state, + int afcex_freq, + unsigned char *AFCEX_L, + unsigned char *AFCEX_H) +{ + int AFCEX ; + + AFCEX = afcex_freq * 8192 / state->master_clk; + *AFCEX_L = AFCEX & 0x00ff; + *AFCEX_H = (AFCEX & 0x0f00) >> 8; +} + +static int SEQ_set(struct mb86a16_state *state, unsigned char loop) +{ + // SLOCK0 = 0 + if (mb86a16_write(state, 0x32, 0x02 | (loop << 2)) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + + return 0; +} + +static int iq_vt_set(struct mb86a16_state *state, unsigned char IQINV) +{ + // Viterbi Rate, IQ Settings + if (mb86a16_write(state, 0x06, 0xdf | (IQINV << 5)) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + + return 0; +} + +static int FEC_srst(struct mb86a16_state *state) +{ + if (mb86a16_write(state, MB86A16_RESET, 0x02) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + + return 0; +} + +static int S2T_set(struct mb86a16_state *state, unsigned char S2T) +{ + if (mb86a16_write(state, 0x34, 0x70 | S2T) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + + return 0; +} + +static int S45T_set(struct mb86a16_state *state, unsigned char S4T, unsigned char S5T) +{ + if (mb86a16_write(state, 0x35, 0x00 | (S5T << 4) | S4T) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + + return 0; +} + + +static int mb86a16_set_fe(struct mb86a16_state *state) +{ + u8 agcval, cnmval; + + int i, j; + int fOSC = 0; + int fOSC_start = 0; + int wait_t; + int fcp; + int swp_ofs; + int V[60]; + u8 SIG1MIN; + + unsigned char CREN, AFCEN, AFCEXEN; + unsigned char SIG1; + unsigned char TIMINT1, TIMINT2, TIMEXT; + unsigned char S0T, S1T; + unsigned char S2T; +// unsigned char S2T, S3T; + unsigned char S4T, S5T; + unsigned char AFCEX_L, AFCEX_H; + unsigned char R; + unsigned char VIRM; + unsigned char ETH, VIA; + unsigned char junk; + + int loop; + int ftemp; + int v, vmax, vmin; + int vmax_his, vmin_his; + int swp_freq, prev_swp_freq[20]; + int prev_freq_num; + int signal_dupl; + int afcex_freq; + int signal; + int afcerr; + int temp_freq, delta_freq; + int dagcm[4]; + int smrt_d; +// int freq_err; + int n; + int ret = -1; + int sync; + + dprintk(verbose, MB86A16_INFO, 1, "freq=%d Mhz, symbrt=%d Ksps", state->frequency, state->srate); + + fcp = 3000; + swp_ofs = state->srate / 4; + + for (i = 0; i < 60; i++) + V[i] = -1; + + for (i = 0; i < 20; i++) + prev_swp_freq[i] = 0; + + SIG1MIN = 25; + + for (n = 0; ((n < 3) && (ret == -1)); n++) { + SEQ_set(state, 0); + iq_vt_set(state, 0); + + CREN = 0; + AFCEN = 0; + AFCEXEN = 1; + TIMINT1 = 0; + TIMINT2 = 1; + TIMEXT = 2; + S1T = 0; + S0T = 0; + + if (initial_set(state) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "initial set failed"); + return -1; + } + if (DAGC_data_set(state, 3, 2) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "DAGC data set error"); + return -1; + } + if (EN_set(state, CREN, AFCEN) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "EN set error"); + return -1; // (0, 0) + } + if (AFCEXEN_set(state, AFCEXEN, state->srate) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error"); + return -1; // (1, smrt) = (1, symbolrate) + } + if (CNTM_set(state, TIMINT1, TIMINT2, TIMEXT) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "CNTM set error"); + return -1; // (0, 1, 2) + } + if (S01T_set(state, S1T, S0T) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "S01T set error"); + return -1; // (0, 0) + } + smrt_info_get(state, state->srate); + if (smrt_set(state, state->srate) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "smrt info get error"); + return -1; + } + + R = vco_dev_get(state, state->srate); + if (R == 1) + fOSC_start = state->frequency; + + else if (R == 0) { + if (state->frequency % 2 == 0) { + fOSC_start = state->frequency; + } else { + fOSC_start = state->frequency + 1; + if (fOSC_start > 2150) + fOSC_start = state->frequency - 1; + } + } + loop = 1; + ftemp = fOSC_start * 1000; + vmax = 0 ; + while (loop == 1) { + ftemp = ftemp + swp_ofs; + vmax++; + + // Upper bound + if (ftemp > 2150000) { + loop = 0; + vmax--; + } + else if ((ftemp == 2150000) || (ftemp - state->frequency * 1000 >= fcp + state->srate / 4)) + loop = 0; + } + + loop = 1; + ftemp = fOSC_start * 1000; + vmin = 0 ; + while (loop == 1) { + ftemp = ftemp - swp_ofs; + vmin--; + + // Lower bound + if (ftemp < 950000) { + loop = 0; + vmin++; + } + else if ((ftemp == 950000) || (state->frequency * 1000 - ftemp >= fcp + state->srate / 4)) + loop = 0; + } + + wait_t = (8000 + state->srate / 2) / state->srate; + if (wait_t == 0) + wait_t = 1; + + i = 0; + j = 0; + prev_freq_num = 0; + loop = 1; + signal = 0; + vmax_his = 0; + vmin_his = 0; + v = 0; + + while (loop == 1) { + swp_info_get(state, fOSC_start, state->srate, + v, R, swp_ofs, &fOSC, + &afcex_freq, &AFCEX_L, &AFCEX_H); + + udelay(100); + if (rf_val_set(state, fOSC, state->srate, R) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "rf val set error"); + return -1; + } + udelay(100); + if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error"); + return -1; + } + if (srst(state) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "srst error"); + return -1; + } + msleep_interruptible(wait_t); + + if (mb86a16_read(state, 0x37, &SIG1) != 2) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -1; + } + V[30 + v] = SIG1 ; + swp_freq = swp_freq_calcuation(state, i, v, V, vmax, vmin, + SIG1MIN, fOSC, afcex_freq, + swp_ofs, &SIG1); //changed + + signal_dupl = 0; + for (j = 0; j < prev_freq_num; j++) { + if ((ABS(prev_swp_freq[j] - swp_freq)) < (swp_ofs * 3 / 2)) { + signal_dupl = 1; + dprintk(verbose, MB86A16_INFO, 1, "Probably Duplicate Signal, j = %d", j); + } + } + if ((signal_dupl == 0) && (swp_freq > 0) && (ABS(swp_freq - state->frequency * 1000) < fcp + state->srate / 6)) { + dprintk(verbose, MB86A16_DEBUG, 1, "------ Signal detect ------ [swp_freq=[%07d, srate=%05d]]", swp_freq, state->srate); + prev_swp_freq[prev_freq_num] = swp_freq; + prev_freq_num++; + swp_info_get2(state, state->srate, R, swp_freq, + &afcex_freq, &fOSC, + &AFCEX_L, &AFCEX_H); + + if (rf_val_set(state, fOSC, state->srate, R) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "rf val set error"); + return -1; + } + if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error"); + return -1; + } + signal = signal_det(state, state->srate, &SIG1); + if (signal == 1) { + dprintk(verbose, MB86A16_ERROR, 1, "***** Signal Found *****"); + loop = 0; + } else { + dprintk(verbose, MB86A16_ERROR, 1, "!!!!! No signal !!!!!, try again..."); + smrt_info_get(state, state->srate); + if (smrt_set(state, state->srate) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "smrt set error"); + return -1; + } + } + } + if (v > vmax) + vmax_his = 1 ; + if (v < vmin) + vmin_his = 1 ; + i++; + + if ((i % 2 == 1) && (vmax_his == 1)) + i++; + if ((i % 2 == 0) && (vmin_his == 1)) + i++; + + if (i % 2 == 1) + v = (i + 1) / 2; + else + v = -i / 2; + + if ((vmax_his == 1) && (vmin_his == 1)) + loop = 0 ; + } + + if (signal == 1) { + dprintk(verbose, MB86A16_INFO, 1, " Start Freq Error Check"); + S1T = 7 ; + S0T = 1 ; + CREN = 0 ; + AFCEN = 1 ; + AFCEXEN = 0 ; + + if (S01T_set(state, S1T, S0T) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "S01T set error"); + return -1; + } + smrt_info_get(state, state->srate); + if (smrt_set(state, state->srate) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "smrt set error"); + return -1; + } + if (EN_set(state, CREN, AFCEN) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "EN set error"); + return -1; + } + if (AFCEXEN_set(state, AFCEXEN, state->srate) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error"); + return -1; + } + afcex_info_get(state, afcex_freq, &AFCEX_L, &AFCEX_H); + if (afcofs_data_set(state, AFCEX_L, AFCEX_H) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "AFCOFS data set error"); + return -1; + } + if (srst(state) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "srst error"); + return -1; + } + // delay 4~200 + wait_t = 200000 / state->master_clk + 200000 / state->srate; + msleep(wait_t); + afcerr = afcerr_chk(state); + if (afcerr == -1) + return -1; + + swp_freq = fOSC * 1000 + afcerr ; + AFCEXEN = 1 ; + if (state->srate >= 1500) + smrt_d = state->srate / 3; + else + smrt_d = state->srate / 2; + smrt_info_get(state, smrt_d); + if (smrt_set(state, smrt_d) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "smrt set error"); + return -1; + } + if (AFCEXEN_set(state, AFCEXEN, smrt_d) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error"); + return -1; + } + R = vco_dev_get(state, smrt_d); + if (DAGC_data_set(state, 2, 0) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "DAGC data set error"); + return -1; + } + for (i = 0; i < 3; i++) { + temp_freq = swp_freq + (i - 1) * state->srate / 8; + swp_info_get2(state, smrt_d, R, temp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H); + if (rf_val_set(state, fOSC, smrt_d, R) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "rf val set error"); + return -1; + } + if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error"); + return -1; + } + wait_t = 200000 / state->master_clk + 40000 / smrt_d; + msleep(wait_t); + dagcm[i] = dagcm_val_get(state); + } + if ((dagcm[0] > dagcm[1]) && + (dagcm[0] > dagcm[2]) && + (dagcm[0] - dagcm[1] > 2 * (dagcm[2] - dagcm[1]))) { + + temp_freq = swp_freq - 2 * state->srate / 8; + swp_info_get2(state, smrt_d, R, temp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H); + if (rf_val_set(state, fOSC, smrt_d, R) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "rf val set error"); + return -1; + } + if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "afcex data set"); + return -1; + } + wait_t = 200000 / state->master_clk + 40000 / smrt_d; + msleep(wait_t); + dagcm[3] = dagcm_val_get(state); + if (dagcm[3] > dagcm[1]) + delta_freq = (dagcm[2] - dagcm[0] + dagcm[1] - dagcm[3]) * state->srate / 300; + else + delta_freq = 0; + } else if ((dagcm[2] > dagcm[1]) && + (dagcm[2] > dagcm[0]) && + (dagcm[2] - dagcm[1] > 2 * (dagcm[0] - dagcm[1]))) { + + temp_freq = swp_freq + 2 * state->srate / 8; + swp_info_get2(state, smrt_d, R, temp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H); + if (rf_val_set(state, fOSC, smrt_d, R) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "rf val set"); + return -1; + } + if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "afcex data set"); + return -1; + } + wait_t = 200000 / state->master_clk + 40000 / smrt_d; + msleep(wait_t); + dagcm[3] = dagcm_val_get(state); + if (dagcm[3] > dagcm[1]) + delta_freq = (dagcm[2] - dagcm[0] + dagcm[3] - dagcm[1]) * state->srate / 300; + else + delta_freq = 0 ; + + } else { + delta_freq = 0 ; + } + dprintk(verbose, MB86A16_INFO, 1, "SWEEP Frequency = %d", swp_freq); + swp_freq += delta_freq; + dprintk(verbose, MB86A16_INFO, 1, "Adjusting .., DELTA Freq = %d, SWEEP Freq=%d", delta_freq, swp_freq); + if (ABS(state->frequency * 1000 - swp_freq) > 3800) { + dprintk(verbose, MB86A16_INFO, 1, "NO -- SIGNAL !"); + } else { + + S1T = 0; + S0T = 3; + CREN = 1; + AFCEN = 0; + AFCEXEN = 1; + + if (S01T_set(state, S1T, S0T) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "S01T set error"); + return -1; + } + if (DAGC_data_set(state, 0, 0) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "DAGC data set error"); + return -1; + } + R = vco_dev_get(state, state->srate); + smrt_info_get(state, state->srate); + if (smrt_set(state, state->srate) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "smrt set error"); + return -1; + } + if (EN_set(state, CREN, AFCEN) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "EN set error"); + return -1; + } + if (AFCEXEN_set(state, AFCEXEN, state->srate) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error"); + return -1; + } + swp_info_get2(state, state->srate, R, swp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H); + if (rf_val_set(state, fOSC, state->srate, R) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "rf val set error"); + return -1; + } + if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error"); + return -1; + } + if (srst(state) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "srst error"); + return -1; + } + wait_t = 7 + (10000 + state->srate / 2) / state->srate; + if (wait_t == 0) + wait_t = 1; + msleep_interruptible(wait_t); + if (mb86a16_read(state, 0x37, &SIG1) != 2) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + + if (SIG1 > 110) { + S2T = 4; S4T = 1; S5T = 6; ETH = 4; VIA = 6; + wait_t = 7 + (917504 + state->srate / 2) / state->srate; + } else if (SIG1 > 105) { + S2T = 4; S4T = 2; S5T = 8; ETH = 7; VIA = 2; + wait_t = 7 + (1048576 + state->srate / 2) / state->srate; + } else if (SIG1 > 85) { + S2T = 5; S4T = 2; S5T = 8; ETH = 7; VIA = 2; + wait_t = 7 + (1310720 + state->srate / 2) / state->srate; + } else if (SIG1 > 65) { + S2T = 6; S4T = 2; S5T = 8; ETH = 7; VIA = 2; + wait_t = 7 + (1572864 + state->srate / 2) / state->srate; + } else { + S2T = 7; S4T = 2; S5T = 8; ETH = 7; VIA = 2; + wait_t = 7 + (2097152 + state->srate / 2) / state->srate; + } + wait_t *= 2; /* FOS */ + S2T_set(state, S2T); + S45T_set(state, S4T, S5T); + Vi_set(state, ETH, VIA); + srst(state); + msleep_interruptible(wait_t); + sync = sync_chk(state, &VIRM); + dprintk(verbose, MB86A16_INFO, 1, "-------- Viterbi=[%d] SYNC=[%d] ---------", VIRM, sync); + if (VIRM) { + if (VIRM == 4) { // 5/6 + if (SIG1 > 110) + wait_t = ( 786432 + state->srate / 2) / state->srate; + else + wait_t = (1572864 + state->srate / 2) / state->srate; + if (state->srate < 5000) + // FIXME ! , should be a long wait ! + msleep_interruptible(wait_t); + else + msleep_interruptible(wait_t); + + if (sync_chk(state, &junk) == 0) { + iq_vt_set(state, 1); + FEC_srst(state); + } + } + // 1/2, 2/3, 3/4, 7/8 + if (SIG1 > 110) + wait_t = ( 786432 + state->srate / 2) / state->srate; + else + wait_t = (1572864 + state->srate / 2) / state->srate; + msleep_interruptible(wait_t); + SEQ_set(state, 1); + } else { + dprintk(verbose, MB86A16_INFO, 1, "NO -- SYNC"); + SEQ_set(state, 1); + } + } + } else { + dprintk (verbose, MB86A16_INFO, 1, "NO -- SIGNAL"); + } + + sync = sync_chk(state, &junk); + if (sync) { + dprintk(verbose, MB86A16_INFO, 1, "******* SYNC *******"); + freqerr_chk(state, state->frequency, state->srate, 1); + break; + } + } + + mb86a16_read(state, 0x15, &agcval); + mb86a16_read(state, 0x26, &cnmval); + dprintk(verbose, MB86A16_INFO, 1, "AGC = %02x CNM = %02x", agcval, cnmval); + + return ret; +} + +static int mb86a16_send_diseqc_msg(struct dvb_frontend *fe, + struct dvb_diseqc_master_cmd *cmd) +{ + struct mb86a16_state *state = fe->demodulator_priv; + int i; + u8 regs; + + if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA) < 0) + goto err; + if (mb86a16_write(state, MB86A16_DCCOUT, 0x00) < 0) + goto err; + if (mb86a16_write(state, MB86A16_TONEOUT2, 0x04) < 0) + goto err; + + regs = 0x18; + + if (cmd->msg_len > 5 || cmd->msg_len < 4) + return -EINVAL; + + for (i = 0; i < cmd->msg_len; i++) { + if (mb86a16_write(state, regs, cmd->msg[i]) < 0) + goto err; + + regs++; + } + i += 0x90; + + msleep_interruptible(10); + + if (mb86a16_write(state, MB86A16_DCC1, i) < 0) + goto err; + if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0) + goto err; + + return 0; + +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int mb86a16_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst) +{ + struct mb86a16_state *state = fe->demodulator_priv; + + switch (burst) { + case SEC_MINI_A: + if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA | + MB86A16_DCC1_TBEN | + MB86A16_DCC1_TBO) < 0) + goto err; + if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0) + goto err; + break; + case SEC_MINI_B: + if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA | + MB86A16_DCC1_TBEN) < 0) + goto err; + if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0) + goto err; + break; + } + + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int mb86a16_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) +{ + struct mb86a16_state *state = fe->demodulator_priv; + + switch (tone) { + case SEC_TONE_ON: + if (mb86a16_write(state, MB86A16_TONEOUT2, 0x00) < 0) + goto err; + if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA | + MB86A16_DCC1_CTOE) < 0) + + goto err; + if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0) + goto err; + break; + case SEC_TONE_OFF: + if (mb86a16_write(state, MB86A16_TONEOUT2, 0x04) < 0) + goto err; + if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA) < 0) + goto err; + if (mb86a16_write(state, MB86A16_DCCOUT, 0x00) < 0) + goto err; + break; + default: + return -EINVAL; + } + return 0; + +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +#define MB86A16_FE_ALGO 1 + +static int mb86a16_frontend_algo(struct dvb_frontend *fe) +{ + return MB86A16_FE_ALGO; +} + +static int mb86a16_set_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p, + unsigned int mode_flags, + int *delay, + fe_status_t *status) +{ + int ret = 0; + struct mb86a16_state *state = fe->demodulator_priv; + + if (p != NULL) { + state->frequency = p->frequency / 1000; + state->srate = p->u.qpsk.symbol_rate / 1000; + ret = mb86a16_set_fe(state); + } + if (!(mode_flags & FE_TUNE_MODE_ONESHOT)) + mb86a16_read_status(fe, status); + + *delay = HZ/3000; + + return ret; +} + +static void mb86a16_release(struct dvb_frontend *fe) +{ + struct mb86a16_state *state = fe->demodulator_priv; + kfree(state); +} + +static int mb86a16_init(struct dvb_frontend *fe) +{ + return 0; +} + +static int mb86a16_sleep(struct dvb_frontend *fe) +{ + return 0; +} + +static int mb86a16_read_ber(struct dvb_frontend *fe, u32 *ber) +{ + u8 ber_mon, ber_tab, ber_lsb, ber_mid, ber_msb, ber_tim, ber_rst; + u32 timer; + + struct mb86a16_state *state = fe->demodulator_priv; + + *ber = 0; + if (mb86a16_read(state, MB86A16_BERMON, &ber_mon) != 2) + goto err; + if (mb86a16_read(state, MB86A16_BERTAB, &ber_tab) != 2) + goto err; + if (mb86a16_read(state, MB86A16_BERLSB, &ber_lsb) != 2) + goto err; + if (mb86a16_read(state, MB86A16_BERMID, &ber_mid) != 2) + goto err; + if (mb86a16_read(state, MB86A16_BERMSB, &ber_msb) != 2) + goto err; + /* BER monitor invalid when BER_EN = 0 */ + if (ber_mon & 0x04) { + /* coarse, fast calculation */ + *ber = ber_tab & 0x1f; + dprintk(verbose, MB86A16_DEBUG, 1, "BER coarse=[0x%02x]", *ber); + if (ber_mon & 0x01) { + /* + * BER_SEL = 1, The monitored BER is the estimated + * value with a Reed-Solomon decoder error amount at + * the deinterleaver output. + * monitored BER is expressed as a 20 bit output in total + */ + ber_rst = ber_mon >> 3; + *ber = (((ber_msb << 8) | ber_mid) << 8) | ber_lsb; + if (ber_rst == 0) + timer = 12500000; + if (ber_rst == 1) + timer = 25000000; + if (ber_rst == 2) + timer = 50000000; + if (ber_rst == 3) + timer = 100000000; + + *ber /= timer; + dprintk(verbose, MB86A16_DEBUG, 1, "BER fine=[0x%02x]", *ber); + } else { + /* + * BER_SEL = 0, The monitored BER is the estimated + * value with a Viterbi decoder error amount at the + * QPSK demodulator output. + * monitored BER is expressed as a 24 bit output in total + */ + ber_tim = ber_mon >> 1; + *ber = (((ber_msb << 8) | ber_mid) << 8) | ber_lsb; + if (ber_tim == 0) + timer = 16; + if (ber_tim == 1) + timer = 24; + + *ber /= 2 ^ timer; + dprintk(verbose, MB86A16_DEBUG, 1, "BER fine=[0x%02x]", *ber); + } + } + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int mb86a16_read_signal_strength(struct dvb_frontend *fe, u16 *strength) +{ + u8 agcm = 0; + struct mb86a16_state *state = fe->demodulator_priv; + + *strength = 0; + if (mb86a16_read(state, MB86A16_AGCM, &agcm) != 2) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + + *strength = ((0xff - agcm) * 100) / 256; + dprintk(verbose, MB86A16_DEBUG, 1, "Signal strength=[%d %%]", (u8) *strength); + *strength = (0xffff - 0xff) + agcm; + + return 0; +} + +struct cnr { + u8 cn_reg; + u8 cn_val; +}; + +static const struct cnr cnr_tab[] = { + { 35, 2 }, + { 40, 3 }, + { 50, 4 }, + { 60, 5 }, + { 70, 6 }, + { 80, 7 }, + { 92, 8 }, + { 103, 9 }, + { 115, 10 }, + { 138, 12 }, + { 162, 15 }, + { 180, 18 }, + { 185, 19 }, + { 189, 20 }, + { 195, 22 }, + { 199, 24 }, + { 201, 25 }, + { 202, 26 }, + { 203, 27 }, + { 205, 28 }, + { 208, 30 } +}; + +static int mb86a16_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + struct mb86a16_state *state = fe->demodulator_priv; + int i = 0; + int low_tide = 2, high_tide = 30, q_level; + u8 cn; + + *snr = 0; + if (mb86a16_read(state, 0x26, &cn) != 2) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + + for (i = 0; i < ARRAY_SIZE(cnr_tab); i++) { + if (cn < cnr_tab[i].cn_reg) { + *snr = cnr_tab[i].cn_val; + break; + } + } + q_level = (*snr * 100) / (high_tide - low_tide); + dprintk(verbose, MB86A16_ERROR, 1, "SNR (Quality) = [%d dB], Level=%d %%", *snr, q_level); + *snr = (0xffff - 0xff) + *snr; + + return 0; +} + +static int mb86a16_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) +{ + u8 dist; + struct mb86a16_state *state = fe->demodulator_priv; + + if (mb86a16_read(state, MB86A16_DISTMON, &dist) != 2) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + *ucblocks = dist; + + return 0; +} + +static struct dvb_frontend_ops mb86a16_ops = { + .info = { + .name = "Fujitsu MB86A16 DVB-S", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 3000, + .frequency_tolerance = 0, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + .symbol_rate_tolerance = 500, + .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | + FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | + FE_CAN_FEC_7_8 | FE_CAN_QPSK | + FE_CAN_FEC_AUTO + }, + .release = mb86a16_release, + .tune = mb86a16_set_frontend, + .read_status = mb86a16_read_status, + .get_frontend_algo = mb86a16_frontend_algo, + .init = mb86a16_init, + .sleep = mb86a16_sleep, + .read_status = mb86a16_read_status, + + .read_ber = mb86a16_read_ber, + .read_signal_strength = mb86a16_read_signal_strength, + .read_snr = mb86a16_read_snr, + .read_ucblocks = mb86a16_read_ucblocks, + + .diseqc_send_master_cmd = mb86a16_send_diseqc_msg, + .diseqc_send_burst = mb86a16_send_diseqc_burst, + .set_tone = mb86a16_set_tone, +}; + +struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config, + struct i2c_adapter *i2c_adap) +{ + u8 dev_id = 0; + struct mb86a16_state *state = NULL; + + state = kmalloc(sizeof (struct mb86a16_state), GFP_KERNEL); + if (state == NULL) + goto error; + + state->config = config; + state->i2c_adap = i2c_adap; + + mb86a16_read(state, 0x7f, &dev_id); + if (dev_id != 0xfe) + goto error; + + memcpy(&state->frontend.ops, &mb86a16_ops, sizeof (struct dvb_frontend_ops)); + state->frontend.demodulator_priv = state; + state->frontend.ops.set_voltage = state->config->set_voltage; + + return &state->frontend; +error: + kfree(state); + return NULL; +} +EXPORT_SYMBOL(mb86a16_attach); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Manu Abraham"); diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/frontends/mb86a16.h linux-2.6.23.1.mantis/drivers/media/dvb/frontends/mb86a16.h --- linux-2.6.23.1/drivers/media/dvb/frontends/mb86a16.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23.1.mantis/drivers/media/dvb/frontends/mb86a16.h 2007-10-10 17:51:19.000000000 +0200 @@ -0,0 +1,38 @@ +/* + Fujitsu MB86A16 DVB-S/DSS DC Receiver driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MB86A16_H +#define __MB86A16_H + +#include +#include "dvb_frontend.h" + + +struct mb86a16_config { + u8 demod_address; + + int (*set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage); +}; + +extern struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config, + struct i2c_adapter *i2c_adap); + + +#endif //__MB86A16_H diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/frontends/mb86a16_priv.h linux-2.6.23.1.mantis/drivers/media/dvb/frontends/mb86a16_priv.h --- linux-2.6.23.1/drivers/media/dvb/frontends/mb86a16_priv.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23.1.mantis/drivers/media/dvb/frontends/mb86a16_priv.h 2007-10-10 17:51:19.000000000 +0200 @@ -0,0 +1,151 @@ +/* + Fujitsu MB86A16 DVB-S/DSS DC Receiver driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MB86A16_PRIV_H +#define __MB86A16_PRIV_H + +#define MB86A16_TSOUT 0x00 +#define MB86A16_TSOUT_HIZSEL (0x01 << 5) +#define MB86A16_TSOUT_HIZCNTI (0x01 << 4) +#define MB86A16_TSOUT_MODE (0x01 << 3) +#define MB86A16_TSOUT_ORDER (0x01 << 2) +#define MB86A16_TSOUT_ERROR (0x01 << 1) +#define Mb86A16_TSOUT_EDGE (0x01 << 0) + +#define MB86A16_FEC 0x01 +#define MB86A16_FEC_FSYNC (0x01 << 5) +#define MB86A16_FEC_PCKB8 (0x01 << 4) +#define MB86A16_FEC_DVDS (0x01 << 3) +#define MB86A16_FEC_EREN (0x01 << 2) +#define Mb86A16_FEC_RSEN (0x01 << 1) +#define MB86A16_FEC_DIEN (0x01 << 0) + +#define MB86A16_AGC 0x02 +#define MB86A16_AGC_AGMD (0x01 << 6) +#define MB86A16_AGC_AGCW (0x0f << 2) +#define MB86A16_AGC_AGCP (0x01 << 1) +#define MB86A16_AGC_AGCR (0x01 << 0) + +#define MB86A16_SRATE1 0x03 +#define MB86A16_SRATE1_DECI (0x07 << 2) +#define MB86A16_SRATE1_CSEL (0x01 << 1) +#define MB86A16_SRATE1_RSEL (0x01 << 0) + +#define MB86A16_SRATE2 0x04 +#define MB86A16_SRATE2_STOFSL (0xff << 0) + +#define MB86A16_SRATE3 0x05 +#define MB86A16_SRATE2_STOFSH (0xff << 0) + +#define MB86A16_VITERBI 0x06 +#define MB86A16_FRAMESYNC 0x07 +#define MB86A16_CRLFILTCOEF1 0x08 +#define MB86A16_CRLFILTCOEF2 0x09 +#define MB86A16_STRFILTCOEF1 0x0a +#define MB86A16_STRFILTCOEF2 0x0b +#define MB86A16_RESET 0x0c +#define MB86A16_STATUS 0x0d +#define MB86A16_AFCML 0x0e +#define MB86A16_AFCMH 0x0f +#define MB86A16_BERMON 0x10 +#define MB86A16_BERTAB 0x11 +#define MB86A16_BERLSB 0x12 +#define MB86A16_BERMID 0x13 +#define MB86A16_BERMSB 0x14 +#define MB86A16_AGCM 0x15 + +#define MB86A16_DCC1 0x16 +#define MB86A16_DCC1_DISTA (0x01 << 7) +#define MB86A16_DCC1_PRTY (0x01 << 6) +#define MB86A16_DCC1_CTOE (0x01 << 5) +#define MB86A16_DCC1_TBEN (0x01 << 4) +#define MB86A16_DCC1_TBO (0x01 << 3) +#define MB86A16_DCC1_NUM (0x07 << 0) + +#define MB86A16_DCC2 0x17 +#define MB86A16_DCC2_DCBST (0x01 << 0) + +#define MB86A16_DCC3 0x18 +#define MB86A16_DCC3_CODE0 (0xff << 0) + +#define MB86A16_DCC4 0x19 +#define MB86A16_DCC4_CODE1 (0xff << 0) + +#define MB86A16_DCC5 0x1a +#define MB86A16_DCC5_CODE2 (0xff << 0) + +#define MB86A16_DCC6 0x1b +#define MB86A16_DCC6_CODE3 (0xff << 0) + +#define MB86A16_DCC7 0x1c +#define MB86A16_DCC7_CODE4 (0xff << 0) + +#define MB86A16_DCC8 0x1d +#define MB86A16_DCC8_CODE5 (0xff << 0) + +#define MB86A16_DCCOUT 0x1e +#define MB86A16_DCCOUT_DISEN (0x01 << 0) + +#define MB86A16_TONEOUT1 0x1f +#define MB86A16_TONE_TDIVL (0xff << 0) + +#define MB86A16_TONEOUT2 0x20 +#define MB86A16_TONE_TMD (0x03 << 2) +#define MB86A16_TONE_TDIVH (0x03 << 0) + +#define MB86A16_FREQ1 0x21 +#define MB86A16_FREQ2 0x22 +#define MB86A16_FREQ3 0x23 +#define MB86A16_FREQ4 0x24 +#define MB86A16_FREQSET 0x25 +#define MB86A16_CNM 0x26 +#define MB86A16_PORT0 0x27 +#define MB86A16_PORT1 0x28 +#define MB86A16_DRCFILT 0x29 +#define MB86A16_AFC 0x2a +#define MB86A16_AFCEXL 0x2b +#define MB86A16_AFCEXH 0x2c +#define MB86A16_DAGC 0x2d +#define MB86A16_SEQMODE 0x32 +#define MB86A16_S0S1T 0x33 +#define MB86A16_S2S3T 0x34 +#define MB86A16_S4S5T 0x35 +#define MB86A16_CNTMR 0x36 +#define MB86A16_SIG1 0x37 +#define MB86A16_SIG2 0x38 +#define MB86A16_VIMAG 0x39 +#define MB86A16_VISET1 0x3a +#define MB86A16_VISET2 0x3b +#define MB86A16_VISET3 0x3c +#define MB86A16_FAGCS1 0x3d +#define MB86A16_FAGCS2 0x3e +#define MB86A16_FAGCS3 0x3f +#define MB86A16_FAGCS4 0x40 +#define MB86A16_FAGCS5 0x41 +#define MB86A16_FAGCS6 0x42 +#define MB86A16_CRM 0x43 +#define MB86A16_STRM 0x44 +#define MB86A16_DAGCML 0x45 +#define MB86A16_DAGCMH 0x46 +#define MB86A16_QPSKTST 0x49 +#define MB86A16_DISTMON 0x52 +#define MB86A16_VERSION 0x7f + +#endif //__MB86A16_PRIV_H diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/Kconfig linux-2.6.23.1.mantis/drivers/media/dvb/Kconfig --- linux-2.6.23.1/drivers/media/dvb/Kconfig 2007-10-12 18:43:44.000000000 +0200 +++ linux-2.6.23.1.mantis/drivers/media/dvb/Kconfig 2007-10-15 12:43:35.000000000 +0200 @@ -40,4 +40,8 @@ comment "Supported DVB Frontends" depends on DVB_CORE source "drivers/media/dvb/frontends/Kconfig" +comment "Supported Mantis Adapters" + depends on DVB_CORE && PCI && I2C +source "drivers/media/dvb/mantis/Kconfig" + endif # DVB_CAPTURE_DRIVERS diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/Makefile linux-2.6.23.1.mantis/drivers/media/dvb/Makefile --- linux-2.6.23.1/drivers/media/dvb/Makefile 2007-10-12 18:43:44.000000000 +0200 +++ linux-2.6.23.1.mantis/drivers/media/dvb/Makefile 2007-10-15 12:43:51.000000000 +0200 @@ -2,4 +2,4 @@ # Makefile for the kernel multimedia device drivers. # -obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/ dvb-usb/ pluto2/ +obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/ dvb-usb/ pluto2/ mantis/ diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/mantis/Kconfig linux-2.6.23.1.mantis/drivers/media/dvb/mantis/Kconfig --- linux-2.6.23.1/drivers/media/dvb/mantis/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23.1.mantis/drivers/media/dvb/mantis/Kconfig 2007-10-10 17:51:19.000000000 +0200 @@ -0,0 +1,13 @@ +config DVB_MANTIS + tristate "MANTIS based cards" + depends on DVB_CORE && PCI && I2C + select DVB_MB86A16 + select DVB_CU1216 + select DVB_ZL10353 + select DVB_STV0299 + select DVB_PLL + help + Support for PCI cards based on the Mantis PCI bridge. + Say Y when you have a Mantis based DVB card and want to use it. + + If unsure say N. diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/mantis/Makefile linux-2.6.23.1.mantis/drivers/media/dvb/mantis/Makefile --- linux-2.6.23.1/drivers/media/dvb/mantis/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23.1.mantis/drivers/media/dvb/mantis/Makefile 2007-10-10 17:51:19.000000000 +0200 @@ -0,0 +1,7 @@ +mantis-objs = mantis_core.o mantis_dma.o mantis_pci.o mantis_i2c.o \ + mantis_dvb.o mantis_vp1033.o mantis_vp1034.o mantis_vp2033.o \ + mantis_vp3030.o + +obj-$(CONFIG_DVB_MANTIS) += mantis.o + +EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/mantis/mantis_common.h linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_common.h --- linux-2.6.23.1/drivers/media/dvb/mantis/mantis_common.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_common.h 2007-10-10 17:51:19.000000000 +0200 @@ -0,0 +1,148 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MANTIS_COMMON_H +#define __MANTIS_COMMON_H + +#include +#include +#include +#include +#include + +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dmxdev.h" +#include "dvb_frontend.h" +#include "dvb_net.h" +#include +#include "mantis_reg.h" + +#define MANTIS_ERROR 0 +#define MANTIS_NOTICE 1 +#define MANTIS_INFO 2 +#define MANTIS_DEBUG 3 + +#define dprintk(x, y, z, format, arg...) do { \ + if (z) { \ + if ((x > MANTIS_ERROR) && (x > y)) \ + printk(KERN_ERR "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ + else if ((x > MANTIS_NOTICE) && (x > y)) \ + printk(KERN_NOTICE "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ + else if ((x > MANTIS_INFO) && (x > y)) \ + printk(KERN_INFO "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ + else if ((x > MANTIS_DEBUG) && (x > y)) \ + printk(KERN_DEBUG "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ + } else { \ + if (x > y) \ + printk(format , ##arg); \ + } \ +} while(0) + +#define mwrite(dat, addr) writel((dat), addr) +#define mread(addr) readl(addr) + +#define mmwrite(dat, addr) mwrite((dat), (mantis->mantis_mmio + (addr))) +#define mmread(addr) mread(mantis->mantis_mmio + (addr)) +#define mmand(dat, addr) mmwrite((dat) & mmread(addr), addr) +#define mmor(dat, addr) mmwrite((dat) | mmread(addr), addr) +#define mmaor(dat, addr) mmwrite((dat) | ((mask) & mmread(addr)), addr) + +#define MANTIS_TS_188 0 +#define MANTIS_TS_204 1 + +struct mantis_hwconfig { + char *model_name; + char *dev_type; + u32 ts_size; +}; + +struct mantis_pci { + /* PCI stuff */ + u16 vendor_id; + u16 device_id; + u16 subsystem_vendor; + u16 subsystem_device; + + u8 latency; + + struct pci_dev *pdev; + + unsigned long mantis_addr; + volatile void __iomem *mantis_mmio; + + u8 irq; + u8 revision; + + unsigned int num; + + /* RISC Core */ + u32 finished_block; + u32 last_block; + u32 line_bytes; + u32 line_count; + u32 risc_pos; + u8 *buf_cpu; + dma_addr_t buf_dma; + u32 *risc_cpu; + dma_addr_t risc_dma; + + struct tasklet_struct tasklet; + + struct i2c_adapter adapter; + int i2c_rc; + wait_queue_head_t i2c_wq; + struct mutex i2c_lock; + + /* DVB stuff */ + struct dvb_adapter dvb_adapter; + struct dvb_frontend *fe; + struct dvb_demux demux; + struct dmxdev dmxdev; + struct dmx_frontend fe_hw; + struct dmx_frontend fe_mem; + struct dvb_net dvbnet; + + u8 feeds; + + struct mantis_hwconfig *hwconfig; + + u32 mantis_int_stat; + u32 mantis_int_mask; + + /* board specific */ + u8 mac_address[8]; + u32 sub_vendor_id; + u32 sub_device_id; + + /* A12 A13 A14 */ + int gpio_status; +}; + +extern unsigned int verbose; +extern unsigned int devs; +extern unsigned int i2c; +extern int mantis_dvb_init(struct mantis_pci *mantis); +extern int mantis_frontend_init(struct mantis_pci *mantis); +extern int mantis_dvb_exit(struct mantis_pci *mantis); +extern void mantis_dma_xfer(unsigned long data); +extern void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value); + +#endif //__MANTIS_COMMON_H diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/mantis/mantis_core.c linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_core.c --- linux-2.6.23.1/drivers/media/dvb/mantis/mantis_core.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_core.c 2007-10-15 12:42:51.000000000 +0200 @@ -0,0 +1,212 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" +#include "mantis_core.h" +#include "mantis_vp1033.h" +#include "mantis_vp1034.h" +#include "mantis_vp2033.h" +#include "mantis_vp3030.h" + +static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) +{ + int err; + struct i2c_msg msg[] = { + { + .addr = 0x50, + .flags = 0, + .buf = data, + .len = 1 + },{ + .addr = 0x50, + .flags = I2C_M_RD, + .buf = data, + .len = length + }, + }; + if ((err = i2c_transfer(&mantis->adapter, msg, 2)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, + "ERROR: i2c read: < err=%i d0=0x%02x d1=0x%02x >", + err, data[0], data[1]); + + return err; + } + + return 0; +} + +static int write_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) +{ + int err; + + struct i2c_msg msg = { + .addr = 0x50, + .flags = 0, + .buf = data, + .len = length + }; + + if ((err = i2c_transfer(&mantis->adapter, &msg, 1)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, + "ERROR: i2c write: < err=%i length=0x%02x d0=0x%02x, d1=0x%02x >", + err, length, data[0], data[1]); + + return err; + } + + return 0; +} + +static int get_mac_address(struct mantis_pci *mantis) +{ + int err; + + mantis->mac_address[0] = 0x08; + if ((err = read_eeprom_byte(mantis, &mantis->mac_address[0], 6)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Mantis EEPROM read error"); + + return err; + } + dprintk(verbose, MANTIS_ERROR, 0, + " MAC Address=[%02x:%02x:%02x:%02x:%02x:%02x]\n", + mantis->mac_address[0], mantis->mac_address[1], + mantis->mac_address[2], mantis->mac_address[3], + mantis->mac_address[4], mantis->mac_address[5]); + + return 0; +} + +#define MANTIS_MODEL_UNKNOWN "UNKNOWN" +#define MANTIS_DEV_UNKNOWN "UNKNOWN" + +struct mantis_hwconfig unknown_device = { + .model_name = MANTIS_MODEL_UNKNOWN, + .dev_type = MANTIS_DEV_UNKNOWN, +}; + +static void mantis_load_config(struct mantis_pci *mantis) +{ + switch (mantis->subsystem_device) { + case MANTIS_VP_1033_DVB_S: // VP-1033 + mantis->hwconfig = &vp1033_mantis_config; + break; + case MANTIS_VP_1034_DVB_S: // VP-1034 + mantis->hwconfig = &vp1034_mantis_config; + break; + case MANTIS_VP_2033_DVB_C: // VP-2033 + mantis->hwconfig = &vp2033_mantis_config; + break; + case MANTIS_VP_3030_DVB_T: // VP-3030 + mantis->hwconfig = &vp3030_mantis_config; + break; + default: + mantis->hwconfig = &unknown_device; + break; + } +} + +int mantis_core_init(struct mantis_pci *mantis) +{ + int err = 0; + + mantis_load_config(mantis); + dprintk(verbose, MANTIS_ERROR, 0, "found a %s PCI %s device on (%02x:%02x.%x),\n", + mantis->hwconfig->model_name, mantis->hwconfig->dev_type, + mantis->pdev->bus->number, PCI_SLOT(mantis->pdev->devfn), PCI_FUNC(mantis->pdev->devfn)); + dprintk(verbose, MANTIS_ERROR, 0, " Mantis Rev %d [%04x:%04x], ", + mantis->revision, + mantis->subsystem_vendor, mantis->subsystem_device); + dprintk(verbose, MANTIS_ERROR, 0, + "irq: %d, latency: %d\n memory: 0x%lx, mmio: 0x%p\n", + mantis->pdev->irq, mantis->latency, + mantis->mantis_addr, mantis->mantis_mmio); + + if ((err = mantis_i2c_init(mantis)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Mantis I2C init failed"); + return err; + } + if ((err = get_mac_address(mantis)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "get MAC address failed"); + return err; + } + if ((err = mantis_dma_init(mantis)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Mantis DMA init failed"); + return err; + } + if ((err = mantis_dvb_init(mantis)) < 0) { + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DVB init failed"); + return err; + } + + return 0; +} + +int mantis_core_exit(struct mantis_pci *mantis) +{ + mantis_dma_stop(mantis); + dprintk(verbose, MANTIS_ERROR, 1, "DMA engine stopping"); + if (mantis_dma_exit(mantis) < 0) + dprintk(verbose, MANTIS_ERROR, 1, "DMA exit failed"); + if (mantis_dvb_exit(mantis) < 0) + dprintk(verbose, MANTIS_ERROR, 1, "DVB exit failed"); + if (mantis_i2c_exit(mantis) < 0) + dprintk(verbose, MANTIS_ERROR, 1, "I2C adapter delete.. failed"); + + return 0; +} + +// Turn the given bit on or off. +void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value) +{ + u32 currVal; + u32 newVal; + + currVal = mmread(MANTIS_GPIF_ADDR); + + if ( value ) + newVal = currVal | ( 1 << bitpos ); + else + newVal = currVal & ( ~ ( 1 << bitpos ) ); + + mmwrite( newVal, MANTIS_GPIF_ADDR); + mmwrite(0x00, MANTIS_GPIF_DOUT); + udelay(100); +} + + +//direction = 0 , no CI passthrough ; 1 , CI passthrough +void mantis_set_direction(struct mantis_pci *mantis, int direction) +{ + u32 reg; + + reg = mmread(0x28); + dprintk(verbose, MANTIS_DEBUG, 1, "TS direction setup"); + if (direction == 0x01) { //to CI + reg |= 0x04; + mmwrite(reg, 0x28); + reg &= 0xff - 0x04; + mmwrite(reg, 0x28); + } else { + reg &= 0xff - 0x04; + mmwrite(reg, 0x28); + reg |= 0x04; + mmwrite(reg, 0x28); + } +} diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/mantis/mantis_core.h linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_core.h --- linux-2.6.23.1/drivers/media/dvb/mantis/mantis_core.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_core.h 2007-10-10 17:51:19.000000000 +0200 @@ -0,0 +1,61 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MANTIS_CORE_H +#define __MANTIS_CORE_H + +#include "mantis_common.h" + + +#define FE_TYPE_SAT 0 +#define FE_TYPE_CAB 1 +#define FE_TYPE_TER 2 + +#define FE_TYPE_TS204 0 +#define FE_TYPE_TS188 1 + + +struct vendorname { + __u8 *sub_vendor_name; + __u32 sub_vendor_id; +}; + +struct devicetype { + __u8 *sub_device_name; + __u32 sub_device_id; + __u8 device_type; + __u32 type_flags; +}; + + +extern int mantis_dma_init(struct mantis_pci *mantis); +extern int mantis_dma_exit(struct mantis_pci *mantis); +extern void mantis_dma_start(struct mantis_pci *mantis); +extern void mantis_dma_stop(struct mantis_pci *mantis); +extern int mantis_i2c_init(struct mantis_pci *mantis); +extern int mantis_i2c_exit(struct mantis_pci *mantis); +extern int mantis_core_init(struct mantis_pci *mantis); +extern int mantis_core_exit(struct mantis_pci *mantis); +//extern void mantis_fe_powerup(struct mantis_pci *mantis); +//extern void mantis_fe_powerdown(struct mantis_pci *mantis); +//extern void mantis_fe_reset(struct dvb_frontend *fe); +extern void mantis_set_direction(struct mantis_pci *mantis, int direction); + +#endif //__MANTIS_CORE_H diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/mantis/mantis_dma.c linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_dma.c --- linux-2.6.23.1/drivers/media/dvb/mantis/mantis_dma.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_dma.c 2007-10-10 17:51:19.000000000 +0200 @@ -0,0 +1,239 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include "mantis_common.h" + +#define RISC_WRITE (0x01 << 28) +#define RISC_JUMP (0x07 << 28) +#define RISC_IRQ (0x01 << 24) + +#define RISC_STATUS(status) ((((~status) & 0x0f) << 20) | ((status & 0x0f) << 16)) +#define RISC_FLUSH() mantis->risc_pos = 0 +#define RISC_INSTR(opcode) mantis->risc_cpu[mantis->risc_pos++] = cpu_to_le32(opcode) + +#define MANTIS_BUF_SIZE 64 * 1024 +#define MANTIS_BLOCK_BYTES (MANTIS_BUF_SIZE >> 4) +#define MANTIS_BLOCK_COUNT (1 << 4) +#define MANTIS_RISC_SIZE PAGE_SIZE + +int mantis_dma_exit(struct mantis_pci *mantis) +{ + if (mantis->buf_cpu) { + dprintk(verbose, MANTIS_ERROR, 1, + "DMA=0x%lx cpu=0x%p size=%d", + (unsigned long) mantis->buf_dma, + mantis->buf_cpu, + MANTIS_BUF_SIZE); + + pci_free_consistent(mantis->pdev, MANTIS_BUF_SIZE, + mantis->buf_cpu, mantis->buf_dma); + + mantis->buf_cpu = NULL; + } + if (mantis->risc_cpu) { + dprintk(verbose, MANTIS_ERROR, 1, + "RISC=0x%lx cpu=0x%p size=%lx", + (unsigned long) mantis->risc_dma, + mantis->risc_cpu, + MANTIS_RISC_SIZE); + + pci_free_consistent(mantis->pdev, MANTIS_RISC_SIZE, + mantis->risc_cpu, mantis->risc_dma); + + mantis->risc_cpu = NULL; + } + + return 0; +} + +static inline int mantis_alloc_buffers(struct mantis_pci *mantis) +{ + if (!mantis->buf_cpu) { + mantis->buf_cpu = pci_alloc_consistent(mantis->pdev, + MANTIS_BUF_SIZE, + &mantis->buf_dma); + if (!mantis->buf_cpu) { + dprintk(verbose, MANTIS_ERROR, 1, + "DMA buffer allocation failed"); + + goto err; + } + dprintk(verbose, MANTIS_ERROR, 1, + "DMA=0x%lx cpu=0x%p size=%d", + (unsigned long) mantis->buf_dma, + mantis->buf_cpu, MANTIS_BUF_SIZE); + } + if (!mantis->risc_cpu) { + mantis->risc_cpu = pci_alloc_consistent(mantis->pdev, + MANTIS_RISC_SIZE, + &mantis->risc_dma); + + if (!mantis->risc_cpu) { + dprintk(verbose, MANTIS_ERROR, 1, + "RISC program allocation failed"); + + mantis_dma_exit(mantis); + + goto err; + } + dprintk(verbose, MANTIS_ERROR, 1, + "RISC=0x%lx cpu=0x%p size=%lx", + (unsigned long) mantis->risc_dma, + mantis->risc_cpu, MANTIS_RISC_SIZE); + } + + return 0; +err: + dprintk(verbose, MANTIS_ERROR, 1, "Out of memory (?) ....."); + return -ENOMEM; +} + +static inline int mantis_calc_lines(struct mantis_pci *mantis) +{ + mantis->line_bytes = MANTIS_BLOCK_BYTES; + mantis->line_count = MANTIS_BLOCK_COUNT; + + while (mantis->line_bytes > 4095) { + mantis->line_bytes >>= 1; + mantis->line_count <<= 1; + } + + dprintk(verbose, MANTIS_DEBUG, 1, + "Mantis RISC block bytes=[%d], line bytes=[%d], line count=[%d]", + MANTIS_BLOCK_BYTES, mantis->line_bytes, mantis->line_count); + + if (mantis->line_count > 255) { + dprintk(verbose, MANTIS_ERROR, 1, "Buffer size error"); + return -EINVAL; + } + + return 0; +} + +int mantis_dma_init(struct mantis_pci *mantis) +{ + int err = 0; + + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DMA init"); + if (mantis_alloc_buffers(mantis) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Error allocating DMA buffer"); + + // Stop RISC Engine +// mmwrite(mmread(MANTIS_DMA_CTL) & ~MANTIS_RISC_EN, MANTIS_DMA_CTL); + mmwrite(0, MANTIS_DMA_CTL); + + goto err; + } + if ((err = mantis_calc_lines(mantis)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Mantis calc lines failed"); + + goto err; + } + + return 0; +err: + return err; +} + +static inline void mantis_risc_program(struct mantis_pci *mantis) +{ + u32 buf_pos = 0; + u32 line; + + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis create RISC program"); + RISC_FLUSH(); + + dprintk(verbose, MANTIS_DEBUG, 1, "risc len lines %u, bytes per line %u", + mantis->line_count, mantis->line_bytes); + + for (line = 0; line < mantis->line_count; line++) { + dprintk(verbose, MANTIS_DEBUG, 1, "RISC PROG line=[%d]", line); + if (!(buf_pos % MANTIS_BLOCK_BYTES)) { + RISC_INSTR(RISC_WRITE | + RISC_IRQ | + RISC_STATUS(((buf_pos / MANTIS_BLOCK_BYTES) + + (MANTIS_BLOCK_COUNT - 1)) % + MANTIS_BLOCK_COUNT) | + mantis->line_bytes); + } else { + RISC_INSTR(RISC_WRITE | mantis->line_bytes); + } + RISC_INSTR(mantis->buf_dma + buf_pos); + buf_pos += mantis->line_bytes; + } + RISC_INSTR(RISC_JUMP); + RISC_INSTR(mantis->risc_dma); +} + +void mantis_dma_start(struct mantis_pci *mantis) +{ + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Start DMA engine"); + + mantis_risc_program(mantis); + mmwrite(mantis->risc_dma, MANTIS_RISC_START); + mmwrite(mmread(MANTIS_GPIF_ADDR) | MANTIS_GPIF_RDWRN, MANTIS_GPIF_ADDR); + + mmwrite(0, MANTIS_DMA_CTL); + mantis->last_block = mantis->finished_block = 0; + + mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_RISCI, MANTIS_INT_MASK); + + mmwrite(MANTIS_FIFO_EN | MANTIS_DCAP_EN + | MANTIS_RISC_EN, MANTIS_DMA_CTL); + +} + +void mantis_dma_stop(struct mantis_pci *mantis) +{ + u32 stat = 0, mask = 0; + + stat = mmread(MANTIS_INT_STAT); + mask = mmread(MANTIS_INT_MASK); + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Stop DMA engine"); + + mmwrite((mmread(MANTIS_GPIF_ADDR) & (~(MANTIS_GPIF_RDWRN))), MANTIS_GPIF_ADDR); + + mmwrite((mmread(MANTIS_DMA_CTL) & ~(MANTIS_FIFO_EN | + MANTIS_DCAP_EN | + MANTIS_RISC_EN)), MANTIS_DMA_CTL); + + mmwrite(mmread(MANTIS_INT_STAT), MANTIS_INT_STAT); + + mmwrite(mmread(MANTIS_INT_MASK) & ~(MANTIS_INT_RISCI | + MANTIS_INT_RISCEN), MANTIS_INT_MASK); +} + + +void mantis_dma_xfer(unsigned long data) +{ + struct mantis_pci *mantis = (struct mantis_pci *) data; + struct mantis_hwconfig *config = mantis->hwconfig; + + while (mantis->last_block != mantis->finished_block) { + dprintk(verbose, MANTIS_DEBUG, 1, "last block=[%d] finished block=[%d]", + mantis->last_block, mantis->finished_block); + + (config->ts_size ? dvb_dmx_swfilter_204: dvb_dmx_swfilter) + (&mantis->demux, &mantis->buf_cpu[mantis->last_block * MANTIS_BLOCK_BYTES], MANTIS_BLOCK_BYTES); + mantis->last_block = (mantis->last_block + 1) % MANTIS_BLOCK_COUNT; + } +} diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/mantis/mantis_dvb.c linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_dvb.c --- linux-2.6.23.1/drivers/media/dvb/mantis/mantis_dvb.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_dvb.c 2007-10-10 17:51:19.000000000 +0200 @@ -0,0 +1,311 @@ +/* + Mantis PCI bridge driver + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include "mantis_common.h" +#include "mantis_core.h" + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "mantis_vp1033.h" +#include "mantis_vp1034.h" +#include "mantis_vp2033.h" +#include "mantis_vp3030.h" + +/* Tuner power supply control */ +void mantis_fe_powerup(struct mantis_pci *mantis) +{ + dprintk(verbose, MANTIS_DEBUG, 1, "Frontend Power ON"); + gpio_set_bits(mantis, 0x0c, 1); + msleep_interruptible(100); + gpio_set_bits(mantis, 0x0c, 1); + msleep_interruptible(100); +} + +void mantis_fe_powerdown(struct mantis_pci *mantis) +{ + dprintk(verbose, MANTIS_DEBUG, 1, "Frontend Power OFF"); + gpio_set_bits(mantis, 0x0c, 0); +} + +static int mantis_fe_reset(struct dvb_frontend *fe) +{ + struct mantis_pci *mantis = fe->dvb->priv; + + dprintk(verbose, MANTIS_DEBUG, 1, "Frontend Reset"); + gpio_set_bits(mantis, 13, 0); + msleep_interruptible(100); + gpio_set_bits(mantis, 13, 0); + msleep_interruptible(100); + gpio_set_bits(mantis, 13, 1); + msleep_interruptible(100); + gpio_set_bits(mantis, 13, 1); + + return 0; +} + +static int mantis_frontend_reset(struct mantis_pci *mantis) +{ + dprintk(verbose, MANTIS_DEBUG, 1, "Frontend Reset"); + gpio_set_bits(mantis, 13, 0); + msleep_interruptible(100); + gpio_set_bits(mantis, 13, 0); + msleep_interruptible(100); + gpio_set_bits(mantis, 13, 1); + msleep_interruptible(100); + gpio_set_bits(mantis, 13, 1); + + return 0; +} + +static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) +{ + struct dvb_demux *dvbdmx = dvbdmxfeed->demux; + struct mantis_pci *mantis = dvbdmx->priv; + + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DVB Start feed"); + if (!dvbdmx->dmx.frontend) { + dprintk(verbose, MANTIS_DEBUG, 1, "no frontend ?"); + return -EINVAL; + } + mantis->feeds++; + dprintk(verbose, MANTIS_DEBUG, 1, + "mantis start feed, feeds=%d", + mantis->feeds); + + if (mantis->feeds == 1) { + dprintk(verbose, MANTIS_DEBUG, 1, "mantis start feed & dma"); + printk("mantis start feed & dma\n"); + mantis_dma_start(mantis); + } + + return mantis->feeds; +} + +static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) +{ + struct dvb_demux *dvbdmx = dvbdmxfeed->demux; + struct mantis_pci *mantis = dvbdmx->priv; + + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DVB Stop feed"); + if (!dvbdmx->dmx.frontend) { + dprintk(verbose, MANTIS_DEBUG, 1, "no frontend ?"); + return -EINVAL; + } + mantis->feeds--; + if (mantis->feeds == 0) { + dprintk(verbose, MANTIS_DEBUG, 1, "mantis stop feed and dma"); + printk("mantis stop feed and dma\n"); + mantis_dma_stop(mantis); + } + return 0; +} + +int __devinit mantis_dvb_init(struct mantis_pci *mantis) +{ + int result; + + dprintk(verbose, MANTIS_DEBUG, 1, "dvb_register_adapter"); + if (dvb_register_adapter(&mantis->dvb_adapter, + "Mantis dvb adapter", THIS_MODULE, + &mantis->pdev->dev) < 0) { + + dprintk(verbose, MANTIS_ERROR, 1, "Error registering adapter"); + return -ENODEV; + } + mantis->dvb_adapter.priv = mantis; + mantis->demux.dmx.capabilities = DMX_TS_FILTERING | + DMX_SECTION_FILTERING | + DMX_MEMORY_BASED_FILTERING; + + mantis->demux.priv = mantis; + mantis->demux.filternum = 256; + mantis->demux.feednum = 256; + mantis->demux.start_feed = mantis_dvb_start_feed; + mantis->demux.stop_feed = mantis_dvb_stop_feed; + mantis->demux.write_to_decoder = NULL; + dprintk(verbose, MANTIS_DEBUG, 1, "dvb_dmx_init"); + if ((result = dvb_dmx_init(&mantis->demux)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, + "dvb_dmx_init failed, ERROR=%d", result); + + goto err0; + } + mantis->dmxdev.filternum = 256; + mantis->dmxdev.demux = &mantis->demux.dmx; + mantis->dmxdev.capabilities = 0; + dprintk(verbose, MANTIS_DEBUG, 1, "dvb_dmxdev_init"); + if ((result = dvb_dmxdev_init(&mantis->dmxdev, + &mantis->dvb_adapter)) < 0) { + + dprintk(verbose, MANTIS_ERROR, 1, + "dvb_dmxdev_init failed, ERROR=%d", result); + goto err1; + } + mantis->fe_hw.source = DMX_FRONTEND_0; + if ((result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, + &mantis->fe_hw)) < 0) { + + dprintk(verbose, MANTIS_ERROR, 1, + "dvb_dmx_init failed, ERROR=%d", result); + + goto err2; + } + mantis->fe_mem.source = DMX_MEMORY_FE; + if ((result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, + &mantis->fe_mem)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, + "dvb_dmx_init failed, ERROR=%d", result); + + goto err3; + } + if ((result = mantis->demux.dmx.connect_frontend(&mantis->demux.dmx, + &mantis->fe_hw)) < 0) { + + dprintk(verbose, MANTIS_ERROR, 1, + "dvb_dmx_init failed, ERROR=%d", result); + + goto err4; + } + dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx); + tasklet_init(&mantis->tasklet, mantis_dma_xfer, (unsigned long) mantis); + mantis_frontend_init(mantis); + return 0; + + /* Error conditions .. */ +err4: + mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); +err3: + mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw); +err2: + dvb_dmxdev_release(&mantis->dmxdev); +err1: + dvb_dmx_release(&mantis->demux); +err0: + dvb_unregister_adapter(&mantis->dvb_adapter); + + return result; +} + +int __devinit mantis_frontend_init(struct mantis_pci *mantis) +{ + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis frontend Init"); + mantis_fe_powerup(mantis); + mantis_frontend_reset(mantis); + dprintk(verbose, MANTIS_DEBUG, 1, "Device ID=%02x", mantis->subsystem_device); + switch (mantis->subsystem_device) { + case MANTIS_VP_1033_DVB_S: // VP-1033 + dprintk(verbose, MANTIS_ERROR, 1, "Probing for STV0299 (DVB-S)"); + mantis->fe = stv0299_attach(&lgtdqcs001f_config, + &mantis->adapter); + + if (mantis->fe) { + mantis->fe->ops.tuner_ops.set_params = lgtdqcs001f_tuner_set; + dprintk(verbose, MANTIS_ERROR, 1, + "found STV0299 DVB-S frontend @ 0x%02x", + lgtdqcs001f_config.demod_address); + + dprintk(verbose, MANTIS_ERROR, 1, + "Mantis DVB-S STV0299 frontend attach success"); + } + break; + case MANTIS_VP_1034_DVB_S: // VP-1034 + dprintk(verbose, MANTIS_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); + mantis->fe = mb86a16_attach(&vp1034_config, &mantis->adapter); + if (mantis->fe) { + dprintk(verbose, MANTIS_ERROR, 1, + "found MB86A16 DVB-S/DSS frontend @0x%02x", + vp1034_config.demod_address); + + } + break; + case MANTIS_VP_2033_DVB_C: // VP-2033 + dprintk(verbose, MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); + mantis->fe = cu1216_attach(&philips_cu1216_config, &mantis->adapter); + if (mantis->fe) { + mantis->fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set; + dprintk(verbose, MANTIS_ERROR, 1, + "found Philips CU1216 DVB-C frontend @ 0x%02x", + philips_cu1216_config.demod_address); + + dprintk(verbose, MANTIS_ERROR, 1, + "Mantis DVB-C Philips CU1216 frontend attach success"); + + } + break; +#if 0 + case MANTIS_VP_3030_DVB_T: // VP-3030 + dprintk(verbose, MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)"); + mantis->fe = zl10353_attach(&mantis_vp3030_config, &mantis->adapter); + if (mantis->fe) { + if (dvb_pll_attach(mantis->fe, + 0x60, + &mantis->adapter, + &dvb_pll_env57h1xd5) < 0) { + + return -EIO; + } + dprintk(verbose, MANTIS_ERROR, 1, + "Mantis DVB-T Zarlink 10353 frontend attach success"); + } + break; +#endif + default: + dprintk(verbose, MANTIS_DEBUG, 1, "Unknown frontend:[0x%02x]", + mantis->sub_device_id); + + return -ENODEV; + } + if (mantis->fe == NULL) { + dprintk(verbose, MANTIS_ERROR, 1, "!!! NO Frontends found !!!"); + return -ENODEV; + } else { + if (dvb_register_frontend(&mantis->dvb_adapter, mantis->fe)) { + dprintk(verbose, MANTIS_ERROR, 1, + "ERROR: Frontend registration failed"); + + if (mantis->fe->ops.release) + mantis->fe->ops.release(mantis->fe); + + mantis->fe = NULL; + return -ENODEV; + } + } + + return 0; +} + +int __devexit mantis_dvb_exit(struct mantis_pci *mantis) +{ + tasklet_kill(&mantis->tasklet); + dvb_net_release(&mantis->dvbnet); + mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); + mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw); + dvb_dmxdev_release(&mantis->dmxdev); + dvb_dmx_release(&mantis->demux); + + if (mantis->fe) + dvb_unregister_frontend(mantis->fe); + dprintk(verbose, MANTIS_DEBUG, 1, "dvb_unregister_adapter"); + dvb_unregister_adapter(&mantis->dvb_adapter); + + return 0; +} diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/mantis/mantis_i2c.c linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_i2c.c --- linux-2.6.23.1/drivers/media/dvb/mantis/mantis_i2c.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_i2c.c 2007-10-10 17:51:19.000000000 +0200 @@ -0,0 +1,192 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "mantis_common.h" + +#define I2C_HW_B_MANTIS 0x1c + +static int mantis_ack_wait(struct mantis_pci *mantis) +{ + int rc = 0; + u32 timeout = 0; + + if (wait_event_interruptible_timeout(mantis->i2c_wq, + mantis->mantis_int_stat & MANTIS_INT_I2CDONE, + msecs_to_jiffies(50)) == -ERESTARTSYS) { + + dprintk(verbose, MANTIS_DEBUG, 1, "Master !I2CDONE"); + rc = -EREMOTEIO; + } + while (!(mantis->mantis_int_stat & MANTIS_INT_I2CRACK)) { + dprintk(verbose, MANTIS_DEBUG, 1, "Waiting for Slave RACK"); + mantis->mantis_int_stat = mmread(MANTIS_INT_STAT); + msleep(5); + timeout++; + if (timeout > 500) { + dprintk(verbose, MANTIS_ERROR, 1, "Slave RACK Fail !"); + rc = -EREMOTEIO; + break; + } + } + udelay(350); + + return rc; +} + +static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) +{ + u32 rxd, i; + + dprintk(verbose, MANTIS_INFO, 0, " %s: Address=[0x%02x] [ ", + __func__, msg->addr); + + for (i = 0; i < msg->len; i++) { + rxd = (msg->addr << 25) | (1 << 24) + | MANTIS_I2C_RATE_3 + | MANTIS_I2C_STOP + | MANTIS_I2C_PGMODE; + + if (i == (msg->len - 1)) + rxd &= ~MANTIS_I2C_STOP; + + mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT); + mmwrite(rxd, MANTIS_I2CDATA_CTL); + if (mantis_ack_wait(mantis) != 0) { + dprintk(verbose, MANTIS_DEBUG, 1, "ACK failed"); + return -EREMOTEIO; + } + rxd = mmread(MANTIS_I2CDATA_CTL); + msg->buf[i] = (u8)((rxd >> 8) & 0xFF); + dprintk(verbose, MANTIS_INFO, 0, "%02x ", msg->buf[i]); + } + dprintk(verbose, MANTIS_INFO, 0, "]\n"); + + return 0; +} + +static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg) +{ + int i; + u32 txd = 0; + + dprintk(verbose, MANTIS_INFO, 0, " %s: Address=[0x%02x] [ ", + __func__, msg->addr); + + for (i = 0; i < msg->len; i++) { + dprintk(verbose, MANTIS_INFO, 0, "%02x ", msg->buf[i]); + txd = (msg->addr << 25) | (msg->buf[i] << 8) + | MANTIS_I2C_RATE_3 + | MANTIS_I2C_STOP + | MANTIS_I2C_PGMODE; + + if (i == (msg->len - 1)) + txd &= ~MANTIS_I2C_STOP; + + mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT); + mmwrite(txd, MANTIS_I2CDATA_CTL); + if (mantis_ack_wait(mantis) != 0) { + dprintk(verbose, MANTIS_DEBUG, 1, "ACK failed"); + return -EREMOTEIO; + } + } + dprintk(verbose, MANTIS_INFO, 0, "]\n"); + + return 0; +} + +static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) +{ + int ret = 0, i; + struct mantis_pci *mantis; + + mantis = i2c_get_adapdata(adapter); + mutex_lock(&mantis->i2c_lock); + for (i = 0; i < num; i++) { + if (msgs[i].flags & I2C_M_RD) + ret = mantis_i2c_read(mantis, &msgs[i]); + else + ret = mantis_i2c_write(mantis, &msgs[i]); + + if (ret < 0) + return ret; + } + mutex_unlock(&mantis->i2c_lock); + + return num; +} + +static u32 mantis_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_SMBUS_EMUL; +} + +static struct i2c_algorithm mantis_algo = { + .master_xfer = mantis_i2c_xfer, + .functionality = mantis_i2c_func, +}; + +static struct i2c_adapter mantis_i2c_adapter = { + .owner = THIS_MODULE, + .name = "Mantis I2C", + .id = I2C_HW_B_MANTIS, + .class = I2C_CLASS_TV_DIGITAL, + .algo = &mantis_algo, +}; + +int __devinit mantis_i2c_init(struct mantis_pci *mantis) +{ + u32 intstat, intmask; + struct i2c_adapter *i2c_adapter = &mantis->adapter; + struct pci_dev *pdev = mantis->pdev; + + mutex_init(&mantis->i2c_lock); + memcpy(i2c_adapter, &mantis_i2c_adapter, sizeof (mantis_i2c_adapter)); + i2c_set_adapdata(i2c_adapter, mantis); + + i2c_adapter->dev.parent = &pdev->dev; + mantis->i2c_rc = i2c_add_adapter(i2c_adapter); + if (mantis->i2c_rc < 0) + return mantis->i2c_rc; + + dprintk(verbose, MANTIS_DEBUG, 1, "Initializing I2C .."); + + intstat = mmread(MANTIS_INT_STAT); + intmask = mmread(MANTIS_INT_MASK); + mmwrite(intstat, MANTIS_INT_STAT); + mmwrite(intmask | MANTIS_INT_I2CDONE, MANTIS_INT_MASK); + + dprintk(verbose, MANTIS_DEBUG, 1, "[0x%08x/%08x]", intstat, intmask); + + return 0; +} + +int __devexit mantis_i2c_exit(struct mantis_pci *mantis) +{ + dprintk(verbose, MANTIS_DEBUG, 1, "Removing I2C adapter"); + return i2c_del_adapter(&mantis->adapter); +} diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/mantis/mantis_pci.c linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_pci.c --- linux-2.6.23.1/drivers/media/dvb/mantis/mantis_pci.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_pci.c 2007-10-10 17:51:19.000000000 +0200 @@ -0,0 +1,285 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include "mantis_common.h" +#include "mantis_core.h" + +#include +#include +#include +#include + +unsigned int verbose = 1; +module_param(verbose, int, 0644); +MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); + +unsigned int devs; + +#define PCI_VENDOR_ID_MANTIS 0x1822 +#define PCI_DEVICE_ID_MANTIS_R11 0x4e35 +#define DRIVER_NAME "Mantis" + +static struct pci_device_id mantis_pci_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_MANTIS, PCI_DEVICE_ID_MANTIS_R11) }, + { 0 }, +}; + +MODULE_DEVICE_TABLE(pci, mantis_pci_table); + +static irqreturn_t mantis_pci_irq(int irq, void *dev_id) +{ + u32 stat = 0, mask = 0, lstat = 0, mstat = 0; + struct mantis_pci *mantis; + + mantis = (struct mantis_pci *) dev_id; + if (unlikely(mantis == NULL)) { + dprintk(verbose, MANTIS_ERROR, 1, "Mantis == NULL"); + return IRQ_NONE; + } + stat = mmread(MANTIS_INT_STAT); + mask = mmread(MANTIS_INT_MASK); + mstat = lstat = stat & ~MANTIS_INT_RISCSTAT; + if (!(stat & mask)) + return IRQ_NONE; + + mantis->mantis_int_stat = stat; + mantis->mantis_int_mask = mask; + dprintk(verbose, MANTIS_DEBUG, 0, "=== Interrupts[%04x/%04x]= [", stat, mask); + if (stat & MANTIS_INT_RISCEN) { + dprintk(verbose, MANTIS_DEBUG, 0, "* DMA enabl *"); + } + if (stat & MANTIS_INT_I2CRACK) { + dprintk(verbose, MANTIS_DEBUG, 0, "* I2C R-ACK *"); + } + if (stat & MANTIS_INT_PCMCIA7) { + dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-07 *"); + } + if (stat & MANTIS_INT_IRQ0) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-0 *"); + } + if (stat & MANTIS_INT_IRQ1) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-1 *"); + } + if (stat & MANTIS_INT_OCERR) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT OCERR *"); + } + if (stat & MANTIS_INT_PABORT) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT PABRT *"); + } + if (stat & MANTIS_INT_RIPERR) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT RIPRR *"); + } + if (stat & MANTIS_INT_PPERR) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT PPERR *"); + } + if (stat & MANTIS_INT_FTRGT) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT FTRGT *"); + } + if (stat & MANTIS_INT_RISCI) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT RISCI *"); + mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28; + tasklet_schedule(&mantis->tasklet); + } + if (stat & MANTIS_INT_I2CDONE) { + dprintk(verbose, MANTIS_DEBUG, 0, "* I2C DONE *"); + wake_up(&mantis->i2c_wq); + } + mmwrite(stat, MANTIS_INT_STAT); + stat &= ~(MANTIS_INT_RISCEN | MANTIS_INT_I2CDONE | + MANTIS_INT_I2CRACK | MANTIS_INT_PCMCIA7 | + MANTIS_INT_PCMCIA6 | MANTIS_INT_PCMCIA5 | + MANTIS_INT_PCMCIA4 | MANTIS_INT_PCMCIA3 | + MANTIS_INT_PCMCIA2 | MANTIS_INT_PCMCIA1 | + MANTIS_INT_PCMCIA0 | MANTIS_INT_IRQ1 | + MANTIS_INT_IRQ0 | MANTIS_INT_OCERR | + MANTIS_INT_PABORT | MANTIS_INT_RIPERR | + MANTIS_INT_PPERR | MANTIS_INT_FTRGT | + MANTIS_INT_RISCI); + + if (stat) + dprintk(verbose, MANTIS_DEBUG, 0, "* Unknown [%04x] *", stat); + + dprintk(verbose, MANTIS_DEBUG, 0, "] ===\n"); + + return IRQ_HANDLED; +} + + +static int __devinit mantis_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *mantis_pci_table) +{ + u8 revision, latency; + struct mantis_pci *mantis; + int ret = 0; + + mantis = kmalloc(sizeof (struct mantis_pci), GFP_KERNEL); + if (mantis == NULL) { + printk("%s: Out of memory\n", __func__); + ret = -ENOMEM; + goto err; + } + memset(mantis, 0, sizeof (struct mantis_pci)); + mantis->num = devs; + devs++; + + if (pci_enable_device(pdev)) { + dprintk(verbose, MANTIS_ERROR, 1, "Mantis PCI enable failed"); + ret = -ENODEV; + goto err; + } + mantis->mantis_addr = pci_resource_start(pdev, 0); + if (!request_mem_region(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0), DRIVER_NAME)) { + ret = -ENODEV; + goto err0; + } + + if ((mantis->mantis_mmio = ioremap(mantis->mantis_addr, 0x1000)) == NULL) { + dprintk(verbose, MANTIS_ERROR, 1, "IO remap failed"); + ret = -ENODEV; + goto err1; + } + + // Clear and disable all interrupts at startup + // to avoid lockup situations + mmwrite(0x00, MANTIS_INT_MASK); + if (request_irq(pdev->irq, mantis_pci_irq, IRQF_SHARED | IRQF_DISABLED, + DRIVER_NAME, mantis) < 0) { + + dprintk(verbose, MANTIS_ERROR, 1, "Mantis IRQ reg failed"); + ret = -ENODEV; + goto err2; + } + pci_set_master(pdev); + pci_set_drvdata(pdev, mantis); + pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency); + pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); + mantis->latency = latency; + mantis->revision = revision; + mantis->pdev = pdev; + mantis->subsystem_vendor = pdev->subsystem_vendor; + mantis->subsystem_device = pdev->subsystem_device; + init_waitqueue_head(&mantis->i2c_wq); + + // CAM bypass + //mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_IRQ1, MANTIS_INT_MASK); + dprintk(verbose, MANTIS_INFO, 0, "\ngpif status: %04x irqcfg: %04x\n", mmread(0x9c), mmread(0x98)); +#if 1 + if ((mmread(0x9c) & 0x200) != 0) { //CAM inserted + msleep_interruptible(1); + if ((mmread(0x9c) & 0x200) != 0) + mmwrite(((mmread(0x98) | 0x01) & ~0x02), 0x98); + else + mmwrite(((mmread(0x98) | 0x02) & ~0x01), 0x98); + + } else { + mmwrite(((mmread(0x98) | 0x02) & ~0x01), 0x98); + } +#endif + mantis_set_direction(mantis, 0); + + if (!latency) + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 32); + + dprintk(verbose, MANTIS_ERROR, 0, + "irq: %d, latency: %d\n memory: 0x%lx, mmio: 0x%p\n", + pdev->irq, mantis->latency, + mantis->mantis_addr, mantis->mantis_mmio); + + // No more PCI specific stuff ! + if (mantis_core_init(mantis) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Mantis core init failed"); + ret = -ENODEV; + goto err2; + } + + return 0; + + // Error conditions .. +err2: + dprintk(verbose, MANTIS_DEBUG, 1, "Err: IO Unmap"); + if (mantis->mantis_mmio) + iounmap(mantis->mantis_mmio); +err1: + dprintk(verbose, MANTIS_DEBUG, 1, "Err: Release regions"); + release_mem_region(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + pci_disable_device(pdev); +err0: + dprintk(verbose, MANTIS_DEBUG, 1, "Err: Free"); + kfree(mantis); +err: + dprintk(verbose, MANTIS_DEBUG, 1, "Err:"); + return ret; +} + +static void __devexit mantis_pci_remove(struct pci_dev *pdev) +{ + struct mantis_pci *mantis = pci_get_drvdata(pdev); + + if (mantis == NULL) { + dprintk(verbose, MANTIS_ERROR, 1, "Aeio, Mantis NULL ptr"); + return; + } + mantis_core_exit(mantis); + dprintk(verbose, MANTIS_ERROR, 1, "Removing -->Mantis irq: %d, latency: %d\n memory: 0x%lx, mmio: 0x%p", + pdev->irq, mantis->latency, mantis->mantis_addr, + mantis->mantis_mmio); + + free_irq(pdev->irq, mantis); + pci_release_regions(pdev); + if (mantis_dma_exit(mantis) < 0) + dprintk(verbose, MANTIS_ERROR, 1, "DMA exit failed"); + + pci_set_drvdata(pdev, NULL); + pci_disable_device(pdev); + kfree(mantis); +} + +static struct pci_driver mantis_pci_driver = { + .name = DRIVER_NAME, + .id_table = mantis_pci_table, + .probe = mantis_pci_probe, + .remove = mantis_pci_remove, +}; + +static int __devinit mantis_pci_init(void) +{ + return pci_register_driver(&mantis_pci_driver); +} + +static void __devexit mantis_pci_exit(void) +{ + pci_unregister_driver(&mantis_pci_driver); +} + +module_init(mantis_pci_init); +module_exit(mantis_pci_exit); + +MODULE_DESCRIPTION("Mantis PCI DTV bridge driver"); +MODULE_AUTHOR("Manu Abraham"); +MODULE_LICENSE("GPL"); diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/mantis/mantis_reg.h linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_reg.h --- linux-2.6.23.1/drivers/media/dvb/mantis/mantis_reg.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_reg.h 2007-10-10 17:51:19.000000000 +0200 @@ -0,0 +1,109 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MANTIS_REG_H +#define __MANTIS_REG_H + +// Interrupts +#define MANTIS_INT_STAT 0x00 +#define MANTIS_INT_MASK 0x04 + +#define MANTIS_INT_RISCSTAT (0x0f << 28) +#define MANTIS_INT_RISCEN (0x01 << 27) +#define MANTIS_INT_I2CRACK (0x01 << 26) + +//#define MANTIS_INT_GPIF (0xff << 12) + +#define MANTIS_INT_PCMCIA7 (0x01 << 19) +#define MANTIS_INT_PCMCIA6 (0x01 << 18) +#define MANTIS_INT_PCMCIA5 (0x01 << 17) +#define MANTIS_INT_PCMCIA4 (0x01 << 16) +#define MANTIS_INT_PCMCIA3 (0x01 << 15) +#define MANTIS_INT_PCMCIA2 (0x01 << 14) +#define MANTIS_INT_PCMCIA1 (0x01 << 13) +#define MANTIS_INT_PCMCIA0 (0x01 << 12) +#define MANTIS_INT_IRQ1 (0x01 << 11) +#define MANTIS_INT_IRQ0 (0x01 << 10) +#define MANTIS_INT_OCERR (0x01 << 8) +#define MANTIS_INT_PABORT (0x01 << 7) +#define MANTIS_INT_RIPERR (0x01 << 6) +#define MANTIS_INT_PPERR (0x01 << 5) +#define MANTIS_INT_FTRGT (0x01 << 3) +#define MANTIS_INT_RISCI (0x01 << 1) +#define MANTIS_INT_I2CDONE (0x01 << 0) + +// DMA +#define MANTIS_DMA_CTL 0x08 +#define MANTIS_I2C_RD (0x01 << 7) +#define MANTIS_I2C_WR (0x01 << 6) +#define MANTIS_DCAP_MODE (0x01 << 5) +#define MANTIS_FIFO_TP_4 (0x00 << 3) +#define MANTIS_FIFO_TP_8 (0x01 << 3) +#define MANTIS_FIFO_TP_16 (0x02 << 3) +#define MANTIS_FIFO_EN (0x01 << 2) +#define MANTIS_DCAP_EN (0x01 << 1) +#define MANTIS_RISC_EN (0x01 << 0) + +#define MANTIS_RISC_START 0x10 +#define MANTIS_RISC_PC 0x14 + +// I2C +#define MANTIS_I2CDATA_CTL 0x18 +#define MANTIS_I2C_RATE_1 (0x00 << 6) +#define MANTIS_I2C_RATE_2 (0x01 << 6) +#define MANTIS_I2C_RATE_3 (0x02 << 6) +#define MANTIS_I2C_RATE_4 (0x03 << 6) +#define MANTIS_I2C_STOP (0x01 << 5) +#define MANTIS_I2C_PGMODE (0x01 << 3) + +#define MANTIS_GPIF_IRQCFG 0x98 +#define MANTIS_GPIF_IRQPOL (0x01 << 8) +#define MANTIS_MASK_WRACK (0x01 << 7) +#define MANTIS_MASK_BRRDY (0x01 << 6) +#define MANTIS_MASK_OVFLW (0x01 << 5) +#define MANTIS_MASK_OTHERR (0x01 << 4) +#define MANTIS_MASK_WSTO (0x01 << 3) +#define MANTIS_MASK_EXTIRQ (0x01 << 2) +#define MANTIS_MASK_PLUGIN (0x01 << 1) +#define MANTIS_MASK_PLUGOUT (0x01 << 0) + +#define MANTIS_GPIF_STATUS 0x9c +#define MANTIS_SBUF_KILLOP (0x01 << 15) +#define MANTIS_SBUF_OPDONE (0x01 << 14) +#define MANTIS_SBUF_EMPTY (0x01 << 13) +#define MANTIS_GPIF_DETSTAT (0x01 << 9) +#define MANTIS_GPIF_INTSTAT (0x01 << 8) +#define MANTIS_GPIF_WRACK (0x01 << 7) +#define MANTIS_GPIF_BRRDY (0x01 << 6) +#define MANTIS_SBUF_OVFLW (0x01 << 5) +#define MANTIS_GPIF_OTHERR (0x01 << 4) +#define MANTIS_SBUF_WSTO (0x01 << 3) +#define MANTIS_GPIF_EXTIRQ (0x01 << 2) +#define MANTIS_CARD_PLUGIN (0x01 << 1) +#define MANTIS_CARD_PLUGOUT (0x01 << 0) + +#define MANTIS_GPIF_ADDR 0xb0 +#define MANTIS_GPIF_RDWRN (0x01 << 31) + +#define MANTIS_GPIF_DOUT 0xb4 +#define MANTIS_GPIF_DIN 0xb8 + + +#endif //__MANTIS_REG_H diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/mantis/mantis_vp1033.c linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_vp1033.c --- linux-2.6.23.1/drivers/media/dvb/mantis/mantis_vp1033.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_vp1033.c 2007-10-10 17:51:19.000000000 +0200 @@ -0,0 +1,160 @@ +/* + Mantis VP-1033 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" +#include "mantis_vp1033.h" + +u8 lgtdqcs001f_inittab[] = { + 0x01, 0x15, + 0x02, 0x00, + 0x03, 0x00, + 0x04, 0x2a, + 0x05, 0x85, + 0x06, 0x02, + 0x07, 0x00, + 0x08, 0x00, + 0x0c, 0x01, + 0x0d, 0x81, + 0x0e, 0x44, + 0x0f, 0x94, + 0x10, 0x3c, + 0x11, 0x84, + 0x12, 0xb9, + 0x13, 0xb5, + 0x14, 0x4f, + 0x15, 0xc9, + 0x16, 0x80, + 0x17, 0x36, + 0x18, 0xfb, + 0x19, 0xcf, + 0x1a, 0xbc, + 0x1c, 0x2b, + 0x1d, 0x27, + 0x1e, 0x00, + 0x1f, 0x0b, + 0x20, 0xa1, + 0x21, 0x60, + 0x22, 0x00, + 0x23, 0x00, + 0x28, 0x00, + 0x29, 0x28, + 0x2a, 0x14, + 0x2b, 0x0f, + 0x2c, 0x09, + 0x2d, 0x05, + 0x31, 0x1f, + 0x32, 0x19, + 0x33, 0xfc, + 0x34, 0x13, + 0xff, 0xff, +}; + +struct stv0299_config lgtdqcs001f_config = { + .demod_address = 0x68, + .inittab = lgtdqcs001f_inittab, + .mclk = 88000000UL, +// .invert = 0, + .invert = 1, +// .enhanced_tuning = 0, + .skip_reinit = 0, + .lock_output = STV0229_LOCKOUTPUT_0, + .volt13_op0_op1 = STV0299_VOLT13_OP0, + .min_delay_ms = 100, + .set_symbol_rate = lgtdqcs001f_set_symbol_rate, +// .pll_set = lgtdqcs001f_pll_set, +}; + +#define MANTIS_MODEL_NAME "VP-1033" +#define MANTIS_DEV_TYPE "DVB-S/DSS" + +struct mantis_hwconfig vp1033_mantis_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_204, +}; + +int lgtdqcs001f_tuner_set(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + u8 buf[4]; + u32 div; + + struct mantis_pci *mantis = fe->dvb->priv; + + struct i2c_msg msg = { + .addr = 0x61, + .flags = 0, + .buf = buf, + .len = sizeof (buf) + }; + div = params->frequency / 250; + + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x83; + buf[3] = 0xc0; + + if (params->frequency < 1531000) + buf[3] |= 0x04; + else + buf[3] &= ~0x04; + if (i2c_transfer(&mantis->adapter, &msg, 1) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Write: I2C Transfer failed"); + return -EIO; + } + msleep_interruptible(100); + + return 0; +} + +int lgtdqcs001f_set_symbol_rate(struct dvb_frontend *fe, + u32 srate, u32 ratio) +{ + u8 aclk = 0; + u8 bclk = 0; + + if (srate < 1500000) { + aclk = 0xb7; + bclk = 0x47; + } else if (srate < 3000000) { + aclk = 0xb7; + bclk = 0x4b; + } else if (srate < 7000000) { + aclk = 0xb7; + bclk = 0x4f; + } else if (srate < 14000000) { + aclk = 0xb7; + bclk = 0x53; + } else if (srate < 30000000) { + aclk = 0xb6; + bclk = 0x53; + } else if (srate < 45000000) { + aclk = 0xb4; + bclk = 0x51; + } + stv0299_writereg (fe, 0x13, aclk); + stv0299_writereg (fe, 0x14, bclk); + + stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg (fe, 0x21, (ratio ) & 0xf0); + + return 0; +} diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/mantis/mantis_vp1033.h linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_vp1033.h --- linux-2.6.23.1/drivers/media/dvb/mantis/mantis_vp1033.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_vp1033.h 2007-10-10 17:51:19.000000000 +0200 @@ -0,0 +1,39 @@ +/* + Mantis VP-1033 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MANTIS_VP1033_H +#define __MANTIS_VP1033_H + +#include "dvb_frontend.h" +#include "mantis_common.h" +#include "stv0299.h" + +#define MANTIS_VP_1033_DVB_S 0x0016 + +extern struct stv0299_config lgtdqcs001f_config; +extern struct mantis_hwconfig vp1033_mantis_config; + +extern int lgtdqcs001f_tuner_set(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params); + +extern int lgtdqcs001f_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio); + + +#endif // __MANTIS_VP1033_H diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/mantis/mantis_vp1034.c linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_vp1034.c --- linux-2.6.23.1/drivers/media/dvb/mantis/mantis_vp1034.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_vp1034.c 2007-10-10 17:51:19.000000000 +0200 @@ -0,0 +1,63 @@ +/* + Mantis VP-1034 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" +#include "mantis_vp1034.h" + +struct mb86a16_config vp1034_config = { + .demod_address = 0x08, + .set_voltage = vp1034_set_voltage, +}; + +#define MANTIS_MODEL_NAME "VP-1034" +#define MANTIS_DEV_TYPE "DVB-S/DSS" + +struct mantis_hwconfig vp1034_mantis_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_204, +}; + +int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +{ + struct mantis_pci *mantis = fe->dvb->priv; + + switch (voltage) { + case SEC_VOLTAGE_13: + dprintk(verbose, MANTIS_ERROR, 1, "Polarization=[13V]"); + gpio_set_bits(mantis, 13, 1); + gpio_set_bits(mantis, 14, 0); + break; + case SEC_VOLTAGE_18: + dprintk(verbose, MANTIS_ERROR, 1, "Polarization=[18V]"); + gpio_set_bits(mantis, 13, 1); + gpio_set_bits(mantis, 14, 1); + break; + case SEC_VOLTAGE_OFF: + dprintk(verbose, MANTIS_ERROR, 1, "Frontend (dummy) POWERDOWN"); + break; + default: + dprintk(verbose, MANTIS_ERROR, 1, "Invalid = (%d)", (u32 ) voltage); + return -EINVAL; + } + mmwrite(0x00, MANTIS_GPIF_DOUT); + + return 0; +} diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/mantis/mantis_vp1034.h linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_vp1034.h --- linux-2.6.23.1/drivers/media/dvb/mantis/mantis_vp1034.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_vp1034.h 2007-10-10 17:51:19.000000000 +0200 @@ -0,0 +1,35 @@ +/* + Mantis VP-1034 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MANTIS_VP1034_H +#define __MANTIS_VP1034_H + +#include "dvb_frontend.h" +#include "mantis_common.h" +#include "mb86a16.h" + + +#define MANTIS_VP_1034_DVB_S 0x0014 + +extern struct mantis_hwconfig vp1034_mantis_config; +extern struct mb86a16_config vp1034_config; +extern int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage); + +#endif // __MANTIS_VP1034_H diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/mantis/mantis_vp2033.c linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_vp2033.c --- linux-2.6.23.1/drivers/media/dvb/mantis/mantis_vp2033.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_vp2033.c 2007-10-10 17:51:19.000000000 +0200 @@ -0,0 +1,70 @@ +/* + Mantis VP-2033 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" +#include "mantis_vp2033.h" + +#define MANTIS_MODEL_NAME "VP-2033" +#define MANTIS_DEV_TYPE "DVB-C" + +struct mantis_hwconfig vp2033_mantis_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_188, +}; + +struct cu1216_config philips_cu1216_config = { + .demod_address = 0x18 >> 1, + .pll_set = philips_cu1216_tuner_set, +// .fe_reset = mantis_fe_reset, +}; + +int philips_cu1216_tuner_set(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + struct mantis_pci *mantis = fe->dvb->priv; + + u8 buf[4]; + + struct i2c_msg msg = { + .addr = 0xc0 >> 1, + .flags = 0, + .buf = buf, + .len = sizeof (buf) + }; + +#define TUNER_MUL 62500 + + u32 div = (params->frequency + 36125000 + TUNER_MUL / 2) / TUNER_MUL; + + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x86; + buf[3] = (params->frequency < 150000000 ? 0xA1 : + params->frequency < 445000000 ? 0x92 : 0x34); + + if (i2c_transfer(&mantis->adapter, &msg, 1) < 0) { + printk("%s tuner not ack!\n", __FUNCTION__); + return -EIO; + } + msleep(100); + + return 0; +} diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/mantis/mantis_vp2033.h linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_vp2033.h --- linux-2.6.23.1/drivers/media/dvb/mantis/mantis_vp2033.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_vp2033.h 2007-10-10 17:51:19.000000000 +0200 @@ -0,0 +1,37 @@ +/* + Mantis VP-2033 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MANTIS_VP2033_H +#define __MANTIS_VP2033_H + +#include "dvb_frontend.h" +#include "mantis_common.h" +#include "cu1216.h" + +#define MANTIS_VP_2033_DVB_C 0x0008 + +extern struct cu1216_config philips_cu1216_config; +extern struct mantis_hwconfig vp2033_mantis_config; + +extern int philips_cu1216_tuner_set(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params); + + +#endif // __MANTIS_VP2033_H diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/mantis/mantis_vp3030.c linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_vp3030.c --- linux-2.6.23.1/drivers/media/dvb/mantis/mantis_vp3030.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_vp3030.c 2007-10-10 17:51:19.000000000 +0200 @@ -0,0 +1,67 @@ +/* + Mantis VP-3030 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" +#include "mantis_vp3030.h" + +struct zl10353_config mantis_vp3030_config = { + .demod_address = 0x0f, +}; + +#define MANTIS_MODEL_NAME "VP-3030" +#define MANTIS_DEV_TYPE "DVB-T" + +struct mantis_hwconfig vp3030_mantis_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_188, +}; + +int panasonic_en57h12d5_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + u8 buf[4]; + int rc; + struct mantis_pci *mantis = fe->dvb->priv; + + struct i2c_msg tuner_msg = { + .addr = 0x60, + .flags = 0, + .buf = buf, + .len = sizeof (buf) + }; + + if ((params->frequency < 950000) || (params->frequency > 2150000)) + return -EINVAL; +#if 0 + rc = dvb_pll_configure(&dvb_pll_env57h1xd5, buf, params->frequency, params->u.ofdm.bandwidth); + if (rc < 0) + return rc; +#endif + rc = i2c_transfer(&mantis->adapter, &tuner_msg, 1); + if (rc != 1) { + printk("%s: I2C Transfer returned [%d]\n", __func__, rc); + return -EIO; + } + msleep_interruptible(1); + printk("%s: Send params to tuner ok!!!\n", __func__); + + return 0; +} diff -u -p -r -P linux-2.6.23.1/drivers/media/dvb/mantis/mantis_vp3030.h linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_vp3030.h --- linux-2.6.23.1/drivers/media/dvb/mantis/mantis_vp3030.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23.1.mantis/drivers/media/dvb/mantis/mantis_vp3030.h 2007-10-10 17:51:19.000000000 +0200 @@ -0,0 +1,34 @@ +/* + Mantis VP-3030 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MANTIS_VP3030_H +#define __MANTIS_VP3030_H + +#include "dvb_frontend.h" +#include "mantis_common.h" +#include "dvb-pll.h" +#include "zl10353.h" + +#define MANTIS_VP_3030_DVB_T 0x0024 + +extern struct zl10353_config mantis_vp3030_config; +extern struct mantis_hwconfig vp3030_mantis_config; + +#endif // __MANTIS_VP3030_H