/* * Driver for the Sony CXD2843ER DVB-T/T2/C/C2 demodulator. * Also supports the CXD2837ER DVB-T/T2/C, the * CXD2838ER ISDB-T demodulator and the * CXD2854 DVB-T/T2/C/C2 ISDB-T demodulator. * * Copyright (C) 2013-2016 Digital Devices GmbH * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 only, as published by the Free Software Foundation. * * * 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., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA * Or, point your browser to http://www.gnu.org/copyleft/gpl.html */ #include #include #include #include #include #include #include #include #include #include #include #include #include "cxd2843.h" #define Log10x100(x) ((s32)(((((u64) intlog2(x) * 0x1e1a5e2e) >> 47 ) + 1) >> 1)) #define USE_ALGO 1 enum demod_type { CXD2843, CXD2837, CXD2838, CXD2854 }; enum demod_state { Unknown, Shutdown, Sleep, ActiveT, ActiveT2, ActiveC, ActiveC2, ActiveIT }; enum t2_profile { T2P_Base, T2P_Lite }; enum omode { OM_NONE, OM_DVBT, OM_DVBT2, OM_DVBC, OM_QAM_ITU_C, OM_DVBC2, OM_ISDBT }; struct cxd_state { struct dvb_frontend frontend; struct i2c_adapter *i2c; struct mutex mutex; u8 adrt; u8 curbankt; u8 adrx; u8 curbankx; enum demod_type type; enum demod_state state; enum t2_profile T2Profile; enum omode omode; u8 IF_FS; int ContinuousClock; int SerialMode; u8 SerialClockFrequency; u32 LockTimeout; u32 TSLockTimeout; u32 L1PostTimeout; u32 DataSliceID; int FirstTimeLock; u32 plp; u32 last_status; u32 bandwidth; u32 bw; unsigned long tune_time; u32 LastBERNumerator; u32 LastBERDenominator; u8 BERScaleMax; u8 is2k14; u8 is24MHz; }; static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) { struct i2c_msg msg = { .addr = adr, .flags = 0, .buf = data, .len = len}; if (i2c_transfer(adap, &msg, 1) != 1) { pr_err("cxd2843: i2c_write error adr %02x data %02x\n", adr, data[0]); return -1; } return 0; } static int writeregs(struct cxd_state *state, u8 adr, u8 reg, u8 *regd, u16 len) { u8 data[16]; if (len >= 15) { pr_err("cxd2843: writeregs length %u too large\n", len); return -1; } data[0] = reg; memcpy(data + 1, regd, len); return i2c_write(state->i2c, adr, data, len + 1); } static int writereg(struct cxd_state *state, u8 adr, u8 reg, u8 dat) { u8 mm[2] = {reg, dat}; return i2c_write(state->i2c, adr, mm, 2); } static int i2c_read(struct i2c_adapter *adap, u8 adr, u8 *msg, int len, u8 *answ, int alen) { struct i2c_msg msgs[2] = { { .addr = adr, .flags = 0, .buf = msg, .len = len}, { .addr = adr, .flags = I2C_M_RD, .buf = answ, .len = alen } }; if (i2c_transfer(adap, msgs, 2) != 2) { pr_err("cxd2843: i2c_read error\n"); return -1; } return 0; } static int readregs(struct cxd_state *state, u8 adr, u8 reg, u8 *val, int count) { return i2c_read(state->i2c, adr, ®, 1, val, count); } static int readregst_unlocked(struct cxd_state *cxd, u8 bank, u8 Address, u8 *pValue, u16 count) { int status = 0; if (bank != 0xFF && cxd->curbankt != bank) { status = writereg(cxd, cxd->adrt, 0, bank); if (status < 0) { cxd->curbankt = 0xFF; return status; } cxd->curbankt = bank; } status = readregs(cxd, cxd->adrt, Address, pValue, count); return status; } static int readregst(struct cxd_state *cxd, u8 Bank, u8 Address, u8 *pValue, u16 count) { int status; mutex_lock(&cxd->mutex); status = readregst_unlocked(cxd, Bank, Address, pValue, count); mutex_unlock(&cxd->mutex); return status; } static int readregsx_unlocked(struct cxd_state *cxd, u8 Bank, u8 Address, u8 *pValue, u16 count) { int status = 0; if (Bank != 0xFF && cxd->curbankx != Bank) { status = writereg(cxd, cxd->adrx, 0, Bank); if (status < 0) { cxd->curbankx = 0xFF; return status; } cxd->curbankx = Bank; } status = readregs(cxd, cxd->adrx, Address, pValue, count); return status; } static int readregsx(struct cxd_state *cxd, u8 Bank, u8 Address, u8 *pValue, u16 count) { int status; mutex_lock(&cxd->mutex); status = readregsx_unlocked(cxd, Bank, Address, pValue, count); mutex_unlock(&cxd->mutex); return status; } static int writeregsx_unlocked(struct cxd_state *cxd, u8 Bank, u8 Address, u8 *pValue, u16 count) { int status = 0; if (Bank != 0xFF && cxd->curbankx != Bank) { status = writereg(cxd, cxd->adrx, 0, Bank); if (status < 0) { cxd->curbankx = 0xFF; return status; } cxd->curbankx = Bank; } status = writeregs(cxd, cxd->adrx, Address, pValue, count); return status; } static int writeregsx(struct cxd_state *cxd, u8 Bank, u8 Address, u8 *pValue, u16 count) { int status; mutex_lock(&cxd->mutex); status = writeregsx_unlocked(cxd, Bank, Address, pValue, count); mutex_unlock(&cxd->mutex); return status; } static int writeregx(struct cxd_state *cxd, u8 Bank, u8 Address, u8 val) { return writeregsx(cxd, Bank, Address, &val, 1); } static int writeregst_unlocked(struct cxd_state *cxd, u8 Bank, u8 Address, u8 *pValue, u16 count) { int status = 0; if (Bank != 0xFF && cxd->curbankt != Bank) { status = writereg(cxd, cxd->adrt, 0, Bank); if (status < 0) { cxd->curbankt = 0xFF; return status; } cxd->curbankt = Bank; } status = writeregs(cxd, cxd->adrt, Address, pValue, count); return status; } static int writeregst(struct cxd_state *cxd, u8 Bank, u8 Address, u8 *pValue, u16 count) { int status; mutex_lock(&cxd->mutex); status = writeregst_unlocked(cxd, Bank, Address, pValue, count); mutex_unlock(&cxd->mutex); return status; } static int writeregt(struct cxd_state *cxd, u8 Bank, u8 Address, u8 val) { return writeregst(cxd, Bank, Address, &val, 1); } static int writebitsx(struct cxd_state *cxd, u8 Bank, u8 Address, u8 Value, u8 Mask) { int status = 0; u8 tmp; mutex_lock(&cxd->mutex); status = readregsx_unlocked(cxd, Bank, Address, &tmp, 1); if (status < 0) goto out; tmp = (tmp & ~Mask) | Value; status = writeregsx_unlocked(cxd, Bank, Address, &tmp, 1); out: mutex_unlock(&cxd->mutex); return status; } static int writebitst(struct cxd_state *cxd, u8 Bank, u8 Address, u8 Value, u8 Mask) { int status = 0; u8 Tmp = 0x00; mutex_lock(&cxd->mutex); status = readregst_unlocked(cxd, Bank, Address, &Tmp, 1); if (status < 0) goto out; Tmp = (Tmp & ~Mask) | Value; status = writeregst_unlocked(cxd, Bank, Address, &Tmp, 1); out: mutex_unlock(&cxd->mutex); return status; } static int freeze_regst(struct cxd_state *cxd) { mutex_lock(&cxd->mutex); return writereg(cxd, cxd->adrt, 1, 1); } static int unfreeze_regst(struct cxd_state *cxd) { int status = 0; status = writereg(cxd, cxd->adrt, 1, 0); mutex_unlock(&cxd->mutex); return status; } static inline u32 MulDiv32(u32 a, u32 b, u32 c) { u64 tmp64; tmp64 = (u64)a * (u64)b; do_div(tmp64, c); return (u32) tmp64; } /* TPSData[0] [7:6] CNST[1:0] */ /* TPSData[0] [5:3] HIER[2:0] */ /* TPSData[0] [2:0] HRATE[2:0] */ /* TPSData[1] [7:5] LRATE[2:0] */ /* TPSData[1] [4:3] GI[1:0] */ /* TPSData[1] [2:1] MODE[1:0] */ /* TPSData[2] [7:6] FNUM[1:0] */ /* TPSData[2] [5:0] LENGTH_INDICATOR[5:0] */ /* TPSData[3] [7:0] CELLID[15:8] */ /* TPSData[4] [7:0] CELLID[7:0] */ /* TPSData[5] [5:0] RESERVE_EVEN[5:0] */ /* TPSData[6] [5:0] RESERVE_ODD[5:0] */ static int read_tps(struct cxd_state *state, u8 *tps) { if (state->last_status != 0x1f) return -1; freeze_regst(state); readregst_unlocked(state, 0x10, 0x2f, tps, 7); unfreeze_regst(state); return 0; } /* Read DVBT2 OFDM Info */ /* OFDMInfo[0] [5] OFDM_MIXED */ /* OFDMInfo[0] [4] OFDM_MISO */ /* OFDMInfo[0] [2:0] OFDM_FFTSIZE[2:0] */ /* OFDMInfo[1] [6:4] OFDM_GI[2:0] */ /* OFDMInfo[1] [2:0] OFDM_PP[2:0] */ /* OFDMInfo[2] [4] OFDM_BWT_EXT */ /* OFDMInfo[2] [3:0] OFDM_PAPR[3:0] */ /* OFDMInfo[3] [3:0] OFDM_NDSYM[11:8] */ /* OFDMInfo[4] [7:0] OFDM_NDSYM[7:0] */ #if 0 static int read_t2_ofdm_info(struct cxd_state *state, u8 *ofdm) { if (state->last_status != 0x1f) return -1; freeze_regst(state); readregst_unlocked(state, 0x20, 0x5c, ofdm, 5); unfreeze_regst(state); return 0; } #endif /* Read DVBT2 QAM, Data PLP 0 [7:0] L1POST_PLP_ID[7:0] 1 [2:0] L1POST_PLP_TYPE[2:0] 2 [4:0] L1POST_PLP_PAYLOAD_TYPE[4:0] 3 [0] L1POST_FF_FLAG 4 [2:0] L1POST_FIRST_RF_IDX[2:0] 5 [7:0] L1POST_FIRST_FRAME_IDX[7:0] 6 [7:0] L1POST_PLP_GROUP_ID[7:0] 7 [2:0] L1POST_PLP_COD[2:0] 8 [2:0] L1POST_PLP_MOD[2:0] 9 [0] L1POST_PLP_ROTATION 10 [1:0] L1POST_PLP_FEC_TYPE[1:0] 11 [1:0] L1POST_PLP_NUM_BLOCKS_MAX[9:8] 12 [7:0] L1POST_PLP_NUM_BLOCKS_MAX[7:0] 13 [7:0] L1POST_FRAME_INTERVAL[7:0] 14 [7:0] L1POST_TIME_IL_LENGTH[7:0] 15 [0] L1POST_TIME_IL_TYPE 16 [0] L1POST_IN_BAND_FLAG 17 [7:0] L1POST_RESERVED_1[15:8] 18 [7:0] L1POST_RESERVED_1[7:0] 19-37 same for common PLP */ #if 0 static int read_t2_tlp_info(struct cxd_state *state, u8 off, u8 count, u8 *tlp) { if (state->last_status != 0x1f) return -1; freeze_regst(state); readregst_unlocked(state, 0x22, 0x54 + off, tlp, count); unfreeze_regst(state); return 0; } #endif static void Active_to_Sleep(struct cxd_state *state) { if (state->state <= Sleep) return; writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */ writeregt(state, 0x00, 0x80, 0x3F); /* Enable HighZ 1 */ writeregt(state, 0x00, 0x81, 0xFF); /* Enable HighZ 2 */ writeregx(state, 0x00, 0x18, 0x01); /* Disable ADC 4 */ writeregt(state, 0x00, 0x43, 0x0A); /* Disable ADC 2 */ writeregt(state, 0x00, 0x41, 0x0A); /* Disable ADC 1 */ writeregt(state, 0x00, 0x30, 0x00); /* Disable ADC Clock */ writeregt(state, 0x00, 0x59, 0x00); /* Disable RF Monitor ADC */ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor Clock */ writeregt(state, 0x00, 0x2C, 0x00); /* Disable Demod Clock */ state->state = Sleep; } static void ActiveT2_to_Sleep(struct cxd_state *state) { if (state->state <= Sleep) return; writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */ writeregt(state, 0x00, 0x80, 0x3F); /* Enable HighZ 1 */ writeregt(state, 0x00, 0x81, 0xFF); /* Enable HighZ 2 */ writeregt(state, 0x13, 0x83, 0x40); writeregt(state, 0x13, 0x86, 0x21); writebitst(state, 0x13, 0x9E, 0x09, 0x0F); writeregt(state, 0x13, 0x9F, 0xFB); writeregx(state, 0x00, 0x18, 0x01); /* Disable ADC 4 */ writeregt(state, 0x00, 0x43, 0x0A); /* Disable ADC 2 */ writeregt(state, 0x00, 0x41, 0x0A); /* Disable ADC 1 */ writeregt(state, 0x00, 0x30, 0x00); /* Disable ADC Clock */ writeregt(state, 0x00, 0x59, 0x00); /* Disable RF Monitor ADC */ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor Clock */ writeregt(state, 0x00, 0x2C, 0x00); /* Disable Demod Clock */ state->state = Sleep; } static void ActiveIT_to_Sleep(struct cxd_state *state) { if (state->state <= Sleep) return; writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */ writeregt(state, 0x00, 0x80, 0x3F); /* Enable HighZ 1 */ writeregt(state, 0x00, 0x81, 0xFF); /* Enable HighZ 2 */ if (state->is2k14) { writebitst(state, 0x10, 0x69, 0x05, 0x07); writebitst(state, 0x10, 0x6b, 0x07, 0x07); writebitst(state, 0x10, 0x9d, 0x14, 0xff); writebitst(state, 0x10, 0xd3, 0x00, 0x1f); writebitst(state, 0x10, 0xed, 0x01, 0x01); writebitst(state, 0x10, 0xe2, 0x4e, 0x80); writebitst(state, 0x10, 0xf2, 0x03, 0x10); writebitst(state, 0x10, 0xde, 0x32, 0x3f); writebitst(state, 0x15, 0xde, 0x03, 0x03); writebitst(state, 0x1e, 0x73, 0x00, 0xff); writebitst(state, 0x63, 0x81, 0x01, 0x01); } writeregx(state, 0x00, 0x18, 0x01); /* Disable ADC 4 */ writeregt(state, 0x00, 0x43, 0x0A); /* Disable ADC 2 */ writeregt(state, 0x00, 0x41, 0x0A); /* Disable ADC 1 */ writeregt(state, 0x00, 0x30, 0x00); /* Disable ADC Clock */ writeregt(state, 0x00, 0x59, 0x00); /* Disable RF Monitor ADC */ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor Clock */ writeregt(state, 0x00, 0x2C, 0x00); /* Disable Demod Clock */ state->state = Sleep; } static void ActiveC2_to_Sleep(struct cxd_state *state) { if (state->state <= Sleep) return; writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */ writeregt(state, 0x00, 0x80, 0x3F); /* Enable HighZ 1 */ writeregt(state, 0x00, 0x81, 0xFF); /* Enable HighZ 2 */ writeregt(state, 0x20, 0xC2, 0x11); writebitst(state, 0x25, 0x6A, 0x02, 0x03); { static u8 data[3] = { 0x07, 0x61, 0x36 }; writeregst(state, 0x25, 0x89, data, sizeof(data)); } writebitst(state, 0x25, 0xCB, 0x05, 0x07); { static u8 data[4] = { 0x2E, 0xE0, 0x2E, 0xE0 }; writeregst(state, 0x25, 0xDC, data, sizeof(data)); } writeregt(state, 0x25, 0xE2, 0x2F); writeregt(state, 0x25, 0xE5, 0x2F); writebitst(state, 0x27, 0x20, 0x00, 0x01); writebitst(state, 0x27, 0x35, 0x00, 0x01); writebitst(state, 0x27, 0xD9, 0x19, 0x3F); writebitst(state, 0x2A, 0x78, 0x01, 0x07); writeregt(state, 0x2A, 0x86, 0x08); writeregt(state, 0x2A, 0x88, 0x14); writebitst(state, 0x2B, 0x2B, 0x00, 0x1F); { u8 data[2] = { 0x75, 0x75 }; u8 data24[2] = { 0x89, 0x89 }; if (state->is24MHz) writeregst(state, 0x2D, 0x24, data24, sizeof(data24)); else writeregst(state, 0x2D, 0x24, data, sizeof(data)); } writeregx(state, 0x00, 0x18, 0x01); /* Disable ADC 4 */ writeregt(state, 0x00, 0x43, 0x0A); /* Disable ADC 2 */ writeregt(state, 0x00, 0x41, 0x0A); /* Disable ADC 1 */ writeregt(state, 0x00, 0x30, 0x00); /* Disable ADC Clock */ writeregt(state, 0x00, 0x59, 0x00); /* Disable RF Monitor ADC */ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor Clock */ writeregt(state, 0x00, 0x2C, 0x00); /* Disable Demod Clock */ state->state = Sleep; } static int ConfigureTS(struct cxd_state *state, enum demod_state newDemodState) { int status = 0; u8 OSERCKMODE = state->SerialMode ? 1 : 0; u8 OSERDUTYMODE = state->SerialMode ? 1 : 0; u8 OTSCKPERIOD = 8; u8 OREG_CKSEL_TSIF = state->SerialMode ? state->SerialClockFrequency : 0; if (state->SerialMode && state->SerialClockFrequency >= 3) { OSERCKMODE = 2; OSERDUTYMODE = 2; OTSCKPERIOD = 16; OREG_CKSEL_TSIF = state->SerialClockFrequency - 3; } writebitst(state, 0x00, 0xC4, OSERCKMODE, 0x03); /* OSERCKMODE */ writebitst(state, 0x00, 0xD1, OSERDUTYMODE, 0x03); /* OSERDUTYMODE */ writeregt(state, 0x00, 0xD9, OTSCKPERIOD); /* OTSCKPERIOD */ writebitst(state, 0x00, 0x32, 0x00, 0x01); /* Disable TS IF */ /* OREG_CKSEL_TSIF */ writebitst(state, 0x00, 0x33, OREG_CKSEL_TSIF, 0x03); writebitst(state, 0x00, 0x32, 0x01, 0x01); /* Enable TS IF */ if (newDemodState == ActiveT) writebitst(state, 0x10, 0x66, 0x01, 0x01); if (newDemodState == ActiveC) writebitst(state, 0x40, 0x66, 0x01, 0x01); return status; } #if 0 static int set_tr(struct cxd_state *state, u32 bw, u32 osc24) { u64 tr = 7 *(osc24 ? 0x1800000000 : 0x1480000000); div64_32(tr, bw); printk("TR %016llx\n", tr); return 0; } #endif static void BandSettingT(struct cxd_state *state, u32 iffreq) { u8 IF_data[3] = { (iffreq >> 16) & 0xff, (iffreq >> 8) & 0xff, iffreq & 0xff}; u8 data[] = { 0x01, 0x14 }; writeregst(state, 0x13, 0x9c, data, sizeof(data)); switch (state->bw) { default: case 8: { u8 NF_data[] = { 0x01, 0x02 }; if (state->is24MHz) { u8 TR_data[] = { 0x15, 0x00, 0x00, 0x00, 0x00 }; writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); } else { u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 }; writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); } writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); writebitst(state, 0x10, 0xD7, 0x00, 0x07); if (state->is24MHz) { u8 CL_data[] = { 0x15, 0x28 }; writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); } else { u8 CL_data[] = { 0x01, 0xE0 }; writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); } writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data)); break; } case 7: { u8 NF_data[] = { 0x00, 0x03 }; if (state->is24MHz) { u8 TR_data[] = { 0x18, 0x00, 0x00, 0x00, 0x00 }; writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); } else { u8 TR_data[] = { 0x14, 0x80, 0x00, 0x00, 0x00 }; writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); } writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); writebitst(state, 0x10, 0xD7, 0x02, 0x07); if (state->is24MHz) { u8 CL_data[] = { 0x1f, 0xf8 }; writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); } else { u8 CL_data[] = { 0x12, 0xF8 }; writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); } writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data)); break; } case 6: { u8 NF_data[] = { 0x00, 0x03 }; if (state->is24MHz) { u8 TR_data[] = { 0x1c, 0x00, 0x00, 0x00, 0x00 }; writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); } else { u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA }; writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); } writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); writebitst(state, 0x10, 0xD7, 0x04, 0x07); if (state->is24MHz) { u8 CL_data[] = { 0x25, 0x4c }; writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); } else { u8 CL_data[] = { 0x1F, 0xDC }; writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); } writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data)); break; } case 5: { static u8 NF_data[] = { 0x00, 0x03 }; if (state->is24MHz) { u8 TR_data[] = { 0x21, 0x99, 0x99, 0x99, 0x99 }; writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); } else { static u8 TR_data[] = { 0x1C, 0xB3, 0x33, 0x33, 0x33 }; writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); } writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); writebitst(state, 0x10, 0xD7, 0x06, 0x07); if (state->is24MHz) { static u8 CL_data[] = { 0x2c, 0xc2 }; writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); } else { static u8 CL_data[] = { 0x26, 0x3C }; writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); } writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data)); break; } } } static void Sleep_to_ActiveT(struct cxd_state *state, u32 iffreq) { ConfigureTS(state, ActiveT); writeregx(state, 0x00, 0x17, 0x01); /* Mode */ writeregt(state, 0x00, 0x2C, 0x01); /* Demod Clock */ writeregt(state, 0x00, 0x59, 0x00); /* Disable RF Monitor ADC */ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor Clock */ writeregt(state, 0x00, 0x30, 0x00); /* Enable ADC Clock */ writeregt(state, 0x00, 0x41, 0x1A); /* Enable ADC1 */ { u8 data[2] = { 0x09, 0x54 }; /* 20.5/24 MHz */ /*u8 data[2] = { 0x0A, 0xD4 }; */ /* 41 MHz */ writeregst(state, 0x00, 0x43, data, 2); /* Enable ADC 2+3 */ } writeregx(state, 0x00, 0x18, 0x00); /* Enable ADC 4 */ writebitst(state, 0x10, 0xD2, 0x0C, 0x1F); /* IF AGC Gain */ writeregt(state, 0x11, 0x6A, 0x50); /* BB AGC Target Level */ writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */ writebitst(state, 0x18, 0x36, 0x40, 0x07); /* Pre RS Monitoring */ writebitst(state, 0x18, 0x30, 0x01, 0x01); /* FEC Autorecover */ writebitst(state, 0x18, 0x31, 0x01, 0x01); /* FEC Autorecover */ writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */ writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/ if (state->is24MHz) { u8 data[3] = { 0xdc, 0x6c, 0x00 }; writeregt(state, 0x10, 0xbf, 0x60); writeregst(state, 0x18, 0x24, data, 3); } BandSettingT(state, iffreq); writebitst(state, 0x10, 0x60, 0x11, 0x1f); /* BER scaling */ writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */ writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */ } static void BandSettingT2(struct cxd_state *state, u32 iffreq) { u8 IF_data[3] = {(iffreq >> 16) & 0xff, (iffreq >> 8) & 0xff, iffreq & 0xff}; switch (state->bw) { default: case 8: { /* Timing recovery */ if (state->is24MHz) { u8 TR_data[] = { 0x15, 0x00, 0x00, 0x00, 0x00 }; writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); } else { u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 }; writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); } /* Add EQ Optimisation for tuner here */ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); /* System Bandwidth */ writebitst(state, 0x10, 0xD7, 0x00, 0x07); } break; case 7: { if (state->is24MHz) { u8 TR_data[] = { 0x18, 0x00, 0x00, 0x00, 0x00 }; writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); } else { u8 TR_data[] = { 0x14, 0x80, 0x00, 0x00, 0x00 }; writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); } writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); writebitst(state, 0x10, 0xD7, 0x02, 0x07); } break; case 6: { if (state->is24MHz) { u8 TR_data[] = { 0x1c, 0x00, 0x00, 0x00, 0x00 }; writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); } else { u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA }; writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); } writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); writebitst(state, 0x10, 0xD7, 0x04, 0x07); } break; case 5: { if (state->is24MHz) { u8 TR_data[] = { 0x21, 0x99, 0x99, 0x99, 0x99 }; writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); } else { u8 TR_data[] = { 0x1C, 0xB3, 0x33, 0x33, 0x33 }; writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); } writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); writebitst(state, 0x10, 0xD7, 0x06, 0x07); } break; case 2: /* 1.7 MHz */ { if (state->is24MHz) { u8 TR_data[] = { 0x68, 0x0f, 0xa2, 0x32, 0xd0 }; writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); } else { u8 TR_data[] = { 0x58, 0xE2, 0xAF, 0xE0, 0xBC }; writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); } writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); writebitst(state, 0x10, 0xD7, 0x03, 0x07); } break; } } static void Sleep_to_ActiveT2(struct cxd_state *state, u32 iffreq) { ConfigureTS(state, ActiveT2); writeregx(state, 0x00, 0x17, 0x02); /* Mode */ writeregt(state, 0x00, 0x2C, 0x01); /* Demod Clock */ writeregt(state, 0x00, 0x59, 0x00); /* Disable RF Monitor ADC */ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor Clock */ writeregt(state, 0x00, 0x30, 0x00); /* Enable ADC Clock */ writeregt(state, 0x00, 0x41, 0x1A); /* Enable ADC1 */ { u8 data[2] = { 0x09, 0x54 }; /* 20.5/24 MHz */ /*u8 data[2] = { 0x0A, 0xD4 }; */ /* 41 MHz */ writeregst(state, 0x00, 0x43, data, 2); /* Enable ADC 2+3 */ } writeregx(state, 0x00, 0x18, 0x00); /* Enable ADC 4 */ writebitst(state, 0x10, 0xD2, 0x0C, 0x1F); /* IFAGC coarse gain */ writeregt(state, 0x11, 0x6A, 0x50); /* BB AGC Target Level */ writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */ writeregt(state, 0x20, 0x8B, 0x3C); /* SNR Good count */ writebitst(state, 0x2B, 0x76, 0x20, 0x70); /* Noise Gain ACQ */ writebitst(state, 0x23, 0xe6, 0x00, 0x03); writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */ writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/ writeregt(state, 0x13, 0x83, 0x10); /* T2 Inital settings */ writeregt(state, 0x13, 0x86, 0x34); writebitst(state, 0x13, 0x9E, 0x09, 0x0F); writeregt(state, 0x13, 0x9F, 0xD8); writebitst(state, 0x23, 0x11, 0x20, 0x3F); if (state->is24MHz ) { static u8 data1[] = { 0xEB, 0x03, 0x3B }; static u8 data2[] = { 0x5E, 0x5E, 0x47 }; static u8 data3[] = { 0x3F, 0xFF }; static u8 data4[] = { 0x0B, 0x72 }; static u8 data5[] = { 0x93, 0xF3, 0x00 }; static u8 data6[] = { 0x05, 0xB8, 0xD8 }; static u8 data7[] = { 0x89, 0x89 }; static u8 data8[] = { 0x24, 0x95 }; writeregst(state, 0x11, 0x33, data1, sizeof(data1)); writeregst(state, 0x20, 0x95, data2, sizeof(data2)); writeregt(state, 0x20, 0x99, 0x18); writeregst(state, 0x20, 0xD9, data3, sizeof(data3)); writeregst(state, 0x24, 0x34, data4, sizeof(data4)); writeregst(state, 0x24, 0xD2, data5, sizeof(data5)); writeregst(state, 0x24, 0xDD, data6, sizeof(data6)); writeregt(state, 0x24, 0xE0, 0x00); writeregt(state, 0x25, 0xED, 0x60); writeregt(state, 0x27, 0xFA, 0x34); writeregt(state, 0x2B, 0x4B, 0x2F); writeregt(state, 0x2B, 0x9E, 0x0E); writeregst(state, 0x2D, 0x24, data7, sizeof(data7)); writeregst(state, 0x5E, 0x8C, data8, sizeof(data8)); } BandSettingT2(state, iffreq); writebitst(state, 0x20, 0x72, 0x08, 0x0f); /* BER scaling */ writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */ writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */ } static void BandSettingC(struct cxd_state *state, u32 iffreq) { u8 data[3]; data[0] = (iffreq >> 16) & 0xFF; data[1] = (iffreq >> 8) & 0xFF; data[2] = (iffreq) & 0xFF; writeregst(state, 0x10, 0xB6, data, 3); } static void Sleep_to_ActiveC(struct cxd_state *state, u32 iffreq) { ConfigureTS(state, ActiveC); writeregx(state, 0x00, 0x17, 0x04); /* Mode */ writeregt(state, 0x00, 0x2C, 0x01); /* Demod Clock */ writeregt(state, 0x00, 0x59, 0x00); /* Disable RF Monitor ADC */ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor Clock */ writeregt(state, 0x00, 0x30, 0x00); /* Enable ADC Clock */ writeregt(state, 0x00, 0x41, 0x1A); /* Enable ADC1 */ { u8 data[2] = { 0x09, 0x54 }; /* 20.5/24 MHz */ /*u8 data[2] = { 0x0A, 0xD4 }; */ /* 41 MHz */ writeregst(state, 0x00, 0x43, data, 2); /* Enable ADC 2+3 */ } writeregx(state, 0x00, 0x18, 0x00); /* Enable ADC 4 */ writebitst(state, 0x10, 0xD2, 0x09, 0x1F); /* IF AGC Gain */ writeregt(state, 0x11, 0x6A, 0x48); /* BB AGC Target Level */ writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */ writebitst(state, 0x40, 0xC3, 0x00, 0x04); /* OREG_BNDET_EN_64 */ writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */ writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/ if (state->is24MHz) { u8 data1[2] = { 0x29, 0x09 }; u8 data2[4] = { 0x08, 0x38, 0x83, 0x0E }; u8 data3[3] = { 0xDC, 0x6C, 0x00 }; u8 data4[2] = { 0x77, 0x00 }; writeregst(state,0x40,0x54,data1,2); writeregst(state,0x40,0x8b,data2,4); writeregt(state,0x40,0xBF,0x60); writeregst(state,0x48,0x24,data3,2); writeregst(state,0x49,0x11,data4,2); } BandSettingC(state, iffreq); writebitst(state, 0x40, 0x60, 0x11, 0x1f); /* BER scaling */ writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */ writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */ } static void BandSettingC2(struct cxd_state *state, u32 iffreq) { u8 IF_data[3] = { (iffreq >> 16) & 0xff, (iffreq >> 8) & 0xff, iffreq & 0xff}; switch (state->bw) { default: case 8: { if (state->is24MHz) { u8 TR_data[] = { 0x15, 0x00, 0x00, 0x00, 0x00 }; writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); } else { u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 }; writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); } writebitst(state, 0x27, 0x7a, 0x00, 0x0f); writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); writebitst(state, 0x10, 0xD7, 0x00, 0x07); if (state->is24MHz) { u8 data[2] = { 0x14, 0xa0 }; writeregst(state, 0x50, 0xEC, data, sizeof(data)); writeregt(state, 0x50, 0xEF, 0x14); writeregt(state, 0x50, 0xF1, 0xa0); } else { u8 data[2] = { 0x11, 0x9E }; writeregst(state, 0x50, 0xEC, data, sizeof(data)); writeregt(state, 0x50, 0xEF, 0x11); writeregt(state, 0x50, 0xF1, 0x9E); } } break; case 6: { if (state->is24MHz) { u8 TR_data[] = { 0x1c, 0x00, 0x00, 0x00, 0x00 }; writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); } else { u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA }; writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); } writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); writebitst(state, 0x10, 0xD7, 0x04, 0x07); if (state->is24MHz) { u8 data[2] = { 0x1b, 0x70 }; writeregst(state, 0x50, 0xEC, data, sizeof(data)); writeregt(state, 0x50, 0xEF, 0x1b); writeregt(state, 0x50, 0xF1, 0x70); } else { u8 data[2] = { 0x17, 0x70 }; writeregst(state, 0x50, 0xEC, data, sizeof(data)); writeregt(state, 0x50, 0xEF, 0x17); writeregt(state, 0x50, 0xF1, 0x70); } } break; } } static void Sleep_to_ActiveC2(struct cxd_state *state, u32 iffreq) { ConfigureTS(state, ActiveC2); writeregx(state, 0x00, 0x17, 0x05); /* Mode */ writeregt(state, 0x00, 0x2C, 0x01); /* Demod Clock */ writeregt(state, 0x00, 0x59, 0x00); /* Disable RF Monitor ADC */ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor Clock */ writeregt(state, 0x00, 0x30, 0x00); /* Enable ADC Clock */ writeregt(state, 0x00, 0x41, 0x1A); /* Enable ADC1 */ { u8 data[2] = { 0x09, 0x54 }; /* 20.5/24 MHz */ /*u8 data[2] = { 0x0A, 0xD4 }; */ /* 41 MHz */ writeregst(state, 0x00, 0x43, data, sizeof(data)); /* Enable ADC 2+3 */ } writeregx(state, 0x00, 0x18, 0x00); /* Enable ADC 4 */ writebitst(state, 0x10, 0xD2, 0x0C, 0x1F); /* IFAGC coarse gain */ writeregt(state, 0x11, 0x6A, 0x50); /* BB AGC Target Level */ writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */ writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */ writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/ writeregt(state, 0x20, 0xC2, 0x00); writebitst(state, 0x25, 0x6A, 0x00, 0x03); { u8 data[3] = { 0x0C, 0xD1, 0x40 }; writeregst(state, 0x25, 0x89, data, sizeof(data)); } writebitst(state, 0x25, 0xCB, 0x01, 0x07); { u8 data[4] = { 0x7B, 0x00, 0x7B, 0x00 }; writeregst(state, 0x25, 0xDC, data, sizeof(data)); } writeregt(state, 0x25, 0xE2, 0x30); writeregt(state, 0x25, 0xE5, 0x30); writebitst(state, 0x27, 0x20, 0x01, 0x01); writebitst(state, 0x27, 0x35, 0x01, 0x01); writebitst(state, 0x27, 0xD9, 0x18, 0x3F); writebitst(state, 0x2A, 0x78, 0x00, 0x07); writeregt(state, 0x2A, 0x86, 0x20); writeregt(state, 0x2A, 0x88, 0x32); writebitst(state, 0x2B, 0x2B, 0x10, 0x1F); { u8 data[2] = { 0x01, 0x01 }; writeregst(state, 0x2D, 0x24, data, sizeof(data)); } if (state->is24MHz) { u8 data1[3] = { 0xEB, 0x03, 0x3B }; u8 data2[2] = { 0x3F, 0xFF }; u8 data3[2] = { 0x0B, 0x72 }; u8 data4[3] = { 0x93, 0xF3, 0x00 }; u8 data5[4] = { 0x05, 0xB8, 0xD8, 0x00 }; u8 data6[9] = { 0x18, 0x1E, 0x71, 0x5D, 0xA9, 0x5D, 0xA9, 0x46, 0x3F }; writeregst(state,0x11,0x33,data1,sizeof(data1)); writeregst(state,0x20,0xD9,data2,sizeof(data2)); writeregst(state,0x24,0x34,data3,sizeof(data3)); writeregst(state,0x24,0xD2,data4,sizeof(data4)); writeregst(state,0x24,0xDD,data5,sizeof(data5)); writeregt(state,0x25,0xED,0x60); writeregst(state,0x5E,0xDB,data6,sizeof(data6)); } BandSettingC2(state, iffreq); writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */ writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */ } static void BandSettingIT(struct cxd_state *state, u32 iffreq) { u8 IF_data[3] = { (iffreq >> 16) & 0xff, (iffreq >> 8) & 0xff, iffreq & 0xff}; switch (state->bw) { default: case 8: { if (state->is24MHz) { u8 TR_data[] = { 0x11, 0xb8, 0x00, 0x00, 0x00 }; /* 24 */ writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); } else { u8 TR_data[] = { 0x0F, 0x22, 0x80, 0x00, 0x00 }; /* 20.5/41 */ writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); } /* Add EQ Optimisation for tuner here */ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); writebitst(state, 0x10, 0xD7, 0x00, 0x07); /* System Bandwidth */ if (state->is24MHz) { u8 CL_data[] = { 0x13, 0xfc }; writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); } else { u8 CL_data[] = { 0x15, 0xA8 }; writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); } writebitst(state, 0x12, 0x71, 0x03, 0x07); writeregt(state, 0x15, 0xbe, 0x03); } break; case 7: { if (state->is24MHz) { u8 TR_data[] = { 0x14, 0x40, 0x00, 0x00, 0x00 }; /* 24 */ writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); } else { u8 TR_data[] = { 0x11, 0x4c, 0x00, 0x00, 0x00 }; writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); } writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); writebitst(state, 0x10, 0xD7, 0x02, 0x07); if (state->is24MHz) { u8 CL_data[] = { 0x1a, 0xfa }; writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); } else { u8 CL_data[] = { 0x1B, 0x5D }; writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); } writebitst(state, 0x12, 0x71, 0x03, 0x07); writeregt(state, 0x15, 0xbe, 0x02); } break; case 6: { if (state->is24MHz) { u8 TR_data[] = { 0x17, 0xa0, 0x00, 0x00, 0x00 }; /* 24 */ writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); } else { u8 TR_data[] = { 0x14, 0x2E, 0x00, 0x00, 0x00 }; writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); } writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); writebitst(state, 0x10, 0xD7, 0x04, 0x07); if (state->is24MHz) { u8 CL_data[] = { 0x1f, 0x79 }; writeregst(state, 0x10, 0xd9, CL_data, sizeof(CL_data)); } else { if (state->is2k14) { u8 CL_data[] = { 0x1a, 0xe2 }; writeregst(state, 0x10, 0xd9, CL_data, sizeof(CL_data)); } else { u8 CL_data[] = { 0x1F, 0xec }; writeregst(state, 0x10, 0xd9, CL_data, sizeof(CL_data)); } } writebitst(state, 0x12, 0x71, 0x07, 0x07); writeregt(state, 0x15, 0xbe, 0x02); } break; } } static void Sleep_to_ActiveIT(struct cxd_state *state, u32 iffreq) { ConfigureTS(state, ActiveIT); /* writeregx(state, 0x00,0x17,0x01); */ /* 2838 has only one Mode */ if (state->is2k14) writeregx(state, 0x00, 0x17, 0x06); writeregt(state, 0x00, 0x2C, 0x01); /* Demod Clock */ if (state->is2k14) { writeregt(state, 0x00, 0x59, 0x00); /* Disable RF Monitor ADC */ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor Clock */ } writeregt(state, 0x00, 0x30, 0x00); /* Enable ADC Clock */ writeregt(state, 0x00, 0x41, 0x1A); /* Enable ADC1 */ { u8 data[2] = { 0x09, 0x54 }; /* 20.5 MHz/24 MHz */ /*u8 data[2] = { 0x0A, 0xD4 }; */ /* 41 MHz */ writeregst(state, 0x00, 0x43, data, 2); /* Enable ADC 2+3 */ } writeregx(state, 0x00, 0x18, 0x00); /* Enable ADC 4 */ if (state->is2k14) { writebitst(state, 0x10, 0xd2, 0x0c, 0x1f); writeregt(state, 0x11, 0x6a, 0x50); writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */ writebitst(state, 0x18, 0x30, 0x01, 0x01); writebitst(state, 0x18, 0x31, 0x00, 0x01); writebitst(state, 0x00, 0xce, 0x00, 0x01); writebitst(state, 0x00, 0xcf, 0x00, 0x01); writebitst(state, 0x10, 0x69, 0x04, 0x07); writebitst(state, 0x10, 0x6b, 0x03, 0x07); writebitst(state, 0x10, 0x9d, 0x50, 0xff); writebitst(state, 0x10, 0xd3, 0x06, 0x1f); writebitst(state, 0x10, 0xed, 0x00, 0x01); writebitst(state, 0x10, 0xe2, 0xce, 0x80); writebitst(state, 0x10, 0xf2, 0x13, 0x10); writebitst(state, 0x10, 0xde, 0x2e, 0x3f); writebitst(state, 0x15, 0xde, 0x02, 0x03); writebitst(state, 0x1e, 0x73, 0x68, 0xff); writebitst(state, 0x63, 0x81, 0x00, 0x01); } if (state->is24MHz) { static u8 TSIF_data[2] = { 0x60,0x00 } ; // 24 MHz static u8 data[3] = { 0xB7,0x1B,0x00 }; // 24 MHz writeregst(state, 0x10, 0xBF, TSIF_data, sizeof(TSIF_data)); writeregst(state, 0x60, 0xA8, data, sizeof(data)); } else { u8 TSIF_data[2] = { 0x61, 0x60 } ; /* 20.5/41 MHz */ u8 data[3] = { 0xB9, 0xBA, 0x63 }; /* 20.5/41 MHz */ writeregst(state, 0x10, 0xBF, TSIF_data, sizeof(TSIF_data)); writeregst(state, 0x60, 0xa8, data, sizeof(data)); } if (!state->is2k14) { writeregt(state, 0x10, 0xE2, 0xCE); /* OREG_PNC_DISABLE */ writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */ } BandSettingIT(state, iffreq); writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */ writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */ } static void T2_SetParameters(struct cxd_state *state) { u8 Profile = 0x01; /* Profile Base */ u8 notT2time = state->is24MHz ? 24 : 12; /* early unlock detection time */ if (state->T2Profile == T2P_Lite) { Profile = 0x05; notT2time = state->is24MHz ? 46 : 40; } if (state->plp != 0xffffffff) { state->T2Profile = ((state->plp & 0x100) != 0) ? T2P_Lite : T2P_Base; writeregt(state, 0x23, 0xAF, state->plp); writeregt(state, 0x23, 0xAD, 0x01); } else { state->T2Profile = T2P_Base; writeregt(state, 0x23, 0xAD, 0x00); } writebitst(state, 0x2E, 0x10, Profile, 0x07); writeregt(state, 0x2B, 0x19, notT2time); } static void C2_ReleasePreset(struct cxd_state *state) { { static u8 data[2] = { 0x02, 0x80}; writeregst(state, 0x27, 0xF4, data, sizeof(data)); } writebitst(state, 0x27, 0x51, 0x40, 0xF0); writebitst(state, 0x27, 0x73, 0x07, 0x0F); writebitst(state, 0x27, 0x74, 0x19, 0x3F); writebitst(state, 0x27, 0x75, 0x19, 0x3F); writebitst(state, 0x27, 0x76, 0x19, 0x3F); if (state->bw == 6) { static u8 data[5] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA}; writeregst(state, 0x20, 0x9F, data, sizeof(data)); } else { static u8 data[5] = { 0x11, 0xF0, 0x00, 0x00, 0x00}; writeregst(state, 0x20, 0x9F, data, sizeof(data)); } writebitst(state, 0x27, 0xC9, 0x07, 0x07); writebitst(state, 0x20, 0xC2, 0x11, 0x33); { static u8 data[10] = { 0x16, 0xF0, 0x2B, 0xD8, 0x16, 0x16, 0xF0, 0x2C, 0xD8, 0x16 }; writeregst(state, 0x2A, 0x20, data, sizeof(data)); } { static u8 data[4] = { 0x00, 0x00, 0x00, 0x00 }; writeregst(state, 0x50, 0x6B, data, sizeof(data)); } writebitst(state, 0x50, 0x6F, 0x00, 0x40); /* Disable Preset */ } static void C2_DemodSetting2(struct cxd_state *state) { u8 data[6]; u32 TunePosition = state->frontend.dtv_property_cache.frequency / 1000; if (state->bw == 6) TunePosition = ((TunePosition * 1792) / 3) / 1000; else TunePosition = (TunePosition * 448) / 1000; TunePosition = ((TunePosition + 6) / 12) * 12; pr_info("TunePosition = %u\n", TunePosition); data[0] = ((TunePosition >> 16) & 0xFF); data[1] = ((TunePosition >> 8) & 0xFF); data[2] = (TunePosition & 0xFF); data[3] = 0x02; data[4] = (state->DataSliceID & 0xFF); data[5] = (state->plp & 0xFF); writeregst(state, 0x50, 0x7A, data, sizeof(data)); writebitst(state, 0x50, 0x87, 0x01, 0x01); /* Preset Clear */ } static void Stop(struct cxd_state *state) { writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */ } static void ShutDown(struct cxd_state *state) { switch (state->state) { case ActiveT2: ActiveT2_to_Sleep(state); break; case ActiveC2: ActiveC2_to_Sleep(state); break; case ActiveIT: ActiveIT_to_Sleep(state); break; default: Active_to_Sleep(state); break; } } static int gate_ctrl(struct dvb_frontend *fe, int enable) { struct cxd_state *state = fe->demodulator_priv; return writebitsx(state, 0xFF, 0x08, enable ? 0x01 : 0x00, 0x01); } static void release(struct dvb_frontend *fe) { struct cxd_state *state = fe->demodulator_priv; Stop(state); ShutDown(state); kfree(state); } static int sleep(struct dvb_frontend *fe) { struct cxd_state *state = fe->demodulator_priv; Stop(state); ShutDown(state); return 0; } static int Start(struct cxd_state *state, u32 IntermediateFrequency) { enum demod_state newDemodState = Unknown; u32 iffreq; if (state->state < Sleep) return -EINVAL; iffreq = MulDiv32(IntermediateFrequency, 16777216, state->is24MHz ? 48000000 : 41000000); switch (state->omode) { case OM_DVBT: if (state->type == CXD2838) return -EINVAL; newDemodState = ActiveT; break; case OM_DVBT2: if (state->type == CXD2838) return -EINVAL; newDemodState = ActiveT2; break; case OM_DVBC: case OM_QAM_ITU_C: if (state->type == CXD2838) return -EINVAL; newDemodState = ActiveC; break; case OM_DVBC2: if (state->type != CXD2843 && state->type != CXD2854) return -EINVAL; newDemodState = ActiveC2; break; case OM_ISDBT: if (state->type != CXD2838 && state->type != CXD2854) return -EINVAL; if (state->type == CXD2854 && !state->is24MHz && state->bw != 6) return -EINVAL; newDemodState = ActiveIT; break; default: return -EINVAL; } state->LockTimeout = 0; state->TSLockTimeout = 0; state->L1PostTimeout = 0; state->last_status = 0; state->FirstTimeLock = 1; state->LastBERNumerator = 0; state->LastBERDenominator = 1; state->BERScaleMax = 19; if (state->state == newDemodState) { writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS Output */ switch (newDemodState) { case ActiveT: /* Stick with HP ( 0x01 = LP ) */ writeregt(state, 0x10, 0x67, 0x00); BandSettingT(state, iffreq); state->BERScaleMax = 18; break; case ActiveT2: T2_SetParameters(state); BandSettingT2(state, iffreq); state->BERScaleMax = 12; break; case ActiveC: BandSettingC(state, iffreq); state->BERScaleMax = 19; break; case ActiveC2: BandSettingC2(state, iffreq); C2_ReleasePreset(state); C2_DemodSetting2(state); break; case ActiveIT: BandSettingIT(state, iffreq); break; default: break; } } else { if (state->state > Sleep) { switch (state->state) { case ActiveT2: ActiveT2_to_Sleep(state); break; case ActiveC2: ActiveC2_to_Sleep(state); break; case ActiveIT: ActiveIT_to_Sleep(state); break; default: Active_to_Sleep(state); break; } } switch (newDemodState) { case ActiveT: /* Stick with HP ( 0x01 = LP ) */ writeregt(state, 0x10, 0x67, 0x00); Sleep_to_ActiveT(state, iffreq); state->BERScaleMax = 18; break; case ActiveT2: T2_SetParameters(state); Sleep_to_ActiveT2(state, iffreq); state->BERScaleMax = 12; break; case ActiveC: Sleep_to_ActiveC(state, iffreq); state->BERScaleMax = 19; break; case ActiveC2: Sleep_to_ActiveC2(state, iffreq); C2_ReleasePreset(state); C2_DemodSetting2(state); break; case ActiveIT: Sleep_to_ActiveIT(state, iffreq); break; default: break; } } state->state = newDemodState; writeregt(state, 0x00, 0xFE, 0x01); /* SW Reset */ writeregt(state, 0x00, 0xC3, 0x00); /* Enable TS Output */ return 0; } static int set_parameters(struct dvb_frontend *fe) { int stat; struct cxd_state *state = fe->demodulator_priv; u32 IF; switch (fe->dtv_property_cache.delivery_system) { case SYS_DVBC_ANNEX_A: state->omode = OM_DVBC; break; case SYS_DVBC2: state->omode = OM_DVBC2; break; case SYS_DVBT: state->omode = OM_DVBT; break; case SYS_DVBT2: state->omode = OM_DVBT2; break; case SYS_ISDBT: state->omode = OM_ISDBT; break; default: return -EINVAL; } if (fe->ops.tuner_ops.set_params) fe->ops.tuner_ops.set_params(fe); state->bandwidth = fe->dtv_property_cache.bandwidth_hz; state->bw = (fe->dtv_property_cache.bandwidth_hz + 999999) / 1000000; if (fe->dtv_property_cache.stream_id == NO_STREAM_ID_FILTER) { state->DataSliceID = 0xffffffff; state->plp = 0xffffffff; } else { state->DataSliceID = (fe->dtv_property_cache.stream_id >> 8) & 0xff; state->plp = fe->dtv_property_cache.stream_id & 0xff; } /* printk("PLP = %08x, bw = %u\n", state->plp, state->bw); */ if (fe->ops.tuner_ops.get_if_frequency) fe->ops.tuner_ops.get_if_frequency(fe, &IF); stat = Start(state, IF); return stat; } static void init(struct cxd_state *state) { u8 data[2] = {0x00, 0x00}; /* 20.5 MHz */ state->omode = OM_NONE; state->state = Unknown; writeregx(state, 0xFF, 0x02, 0x00); usleep_range(4000, 5000); writeregx(state, 0x00, 0x15, 0x01); if (state->type != CXD2838) writeregx(state, 0x00, 0x17, 0x01); usleep_range(4000, 5000); writeregx(state, 0x00, 0x10, 0x01); writeregx(state, 0x00, 0x15, 0x00); usleep_range(3000, 4000); writeregsx(state, 0x00, 0x13, data, 0); if (state->is24MHz) writeregx(state, 0x00, 0x12, 0x00); writeregx(state, 0x00, 0x14, state->is24MHz ? 0x03 : 0x00); writeregx(state, 0x00, 0x10, 0x00); usleep_range(2000, 3000); state->curbankx = 0xFF; state->curbankt = 0xFF; writeregt(state, 0x00, 0x43, 0x0A); writeregt(state, 0x00, 0x41, 0x0A); if (state->type == CXD2838) writeregt(state, 0x60, 0x5A, 0x00); if (state->type == CXD2854) { writeregt(state, 0x00, 0x63, 0x16); writeregt(state, 0x00, 0x65, 0x27); writeregt(state, 0x00, 0x69, 0x06); } writebitst(state, 0x10, 0xCB, 0x00, 0x40); writeregt(state, 0x10, 0xCD, state->IF_FS); writebitst(state, 0x00, 0xC4, state->SerialMode ? 0x80 : 0x00, 0x98); writebitst(state, 0x00, 0xC5, 0x01, 0x07); writebitst(state, 0x00, 0xCB, 0x00, 0x01); writebitst(state, 0x00, 0xC6, 0x00, 0x1D); writebitst(state, 0x00, 0xC8, 0x01, 0x1D); writebitst(state, 0x00, 0xC9, 0x00, 0x1D); writebitst(state, 0x00, 0x83, 0x00, 0x07); writeregt(state, 0x00, 0x84, 0x00); writebitst(state, 0x00, 0xD3, (state->type == CXD2838) ? 0x01 : 0x00, 0x01); writebitst(state, 0x00, 0xDE, 0x00, 0x01); state->state = Sleep; } static void init_state(struct cxd_state *state, struct cxd2843_cfg *cfg) { state->adrt = cfg->adr; state->adrx = cfg->adr + 0x02; state->curbankt = 0xff; state->curbankx = 0xff; mutex_init(&state->mutex); state->SerialMode = cfg->parallel ? 0 : 1; state->ContinuousClock = 1; state->SerialClockFrequency = (cfg->ts_clock >= 1 && cfg->ts_clock <= 5) ? cfg->ts_clock : 1; /* 1 = fastest (82 MBit/s), 5 = slowest */ /* IF Fullscale 0x50 = 1.4V, 0x39 = 1V, 0x28 = 0.7V */ state->IF_FS = 0x50; state->is24MHz = (cfg->osc == 24000000) ? 1 : 0; printk("is24Mhz = %u\n", state->is24MHz); } static int get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *sets) { switch (fe->dtv_property_cache.delivery_system) { case SYS_DVBC_ANNEX_A: case SYS_DVBC_ANNEX_C: /*return c_get_tune_settings(fe, sets);*/ default: /* DVB-T: Use info.frequency_stepsize. */ return -EINVAL; } } static int read_snr(struct dvb_frontend *fe, u16 *snr); static int get_stats(struct dvb_frontend *fe) { struct dtv_frontend_properties *p = &fe->dtv_property_cache; u16 val; s64 str; if (fe->ops.tuner_ops.get_rf_strength) fe->ops.tuner_ops.get_rf_strength(fe, &val); else val = 0; str = 1000 * (s64) (s16) val; str -= 108750; p->strength.len = 1; p->strength.stat[0].scale = FE_SCALE_DECIBEL; p->strength.stat[0].svalue = str; read_snr(fe, &val); p->cnr.len = 1; p->cnr.stat[0].scale = FE_SCALE_DECIBEL; p->cnr.stat[0].svalue = 100 * (s64) (s16) val; return 0; } static int read_status(struct dvb_frontend *fe, enum fe_status *status) { struct cxd_state *state = fe->demodulator_priv; u8 rdata; get_stats(fe); *status = 0; switch (state->state) { case ActiveC: readregst(state, 0x40, 0x88, &rdata, 1); if (rdata & 0x02) break; if (rdata & 0x01) { *status |= 0x07; readregst(state, 0x40, 0x10, &rdata, 1); if (rdata & 0x20) *status |= 0x1f; } if (*status == 0x1f && state->FirstTimeLock) { readregst(state, 0x40, 0x19, &rdata, 1); rdata &= 0x07; state->BERScaleMax = ( rdata < 2 ) ? 18 : 19; state->FirstTimeLock = 0; } break; case ActiveT: readregst(state, 0x10, 0x10, &rdata, 1); if (rdata & 0x10) break; if ((rdata & 0x07) == 0x06) { *status |= 0x07; if (rdata & 0x20) *status |= 0x1f; } if (*status == 0x1f && state->FirstTimeLock) { u8 tps[7]; read_tps(state, tps); state->BERScaleMax = (((tps[0] >> 6) & 0x03) < 2 ) ? 17 : 18; if ((tps[0] & 7) < 2) state->BERScaleMax--; state->FirstTimeLock = 0; } break; case ActiveT2: readregst(state, 0x20, 0x10, &rdata, 1); if (rdata & 0x10) break; if ((rdata & 0x07) == 0x06) { *status |= 0x07; if (rdata & 0x20) *status |= 0x08; } if (*status & 0x08) { readregst(state, 0x22, 0x12, &rdata, 1); if (rdata & 0x01) *status |= 0x10; } break; case ActiveC2: readregst(state, 0x20, 0x10, &rdata, 1); if (rdata & 0x10) break; if ((rdata & 0x07) == 0x06) { *status |= 0x07; if (rdata & 0x20) *status |= 0x18; } if ((*status & 0x10) && state->FirstTimeLock) { u8 data; /* Change1stTrial */ readregst(state, 0x28, 0xE6, &rdata, 1); data = rdata & 1; readregst(state, 0x50, 0x15, &rdata, 1); data |= ((rdata & 0x18) >> 2); /*writebitst(state, 0x50,0x6F,rdata,0x07);*/ state->FirstTimeLock = 0; } break; case ActiveIT: readregst(state, 0x60, 0x10, &rdata, 1); if (rdata & 0x10) break; if (rdata & 0x02) { *status |= 0x07; if (rdata & 0x01) *status |= 0x18; } if (*status == 0x1f && state->FirstTimeLock) { /* readregst(state, 0x40, 0x19, &rdata, 1); */ /* rdata &= 0x07; */ /* state->BERScaleMax = ( rdata < 2 ) ? 18 : 19; */ state->FirstTimeLock = 0; } break; default: break; } state->last_status = *status; return 0; } static int get_ber_t(struct cxd_state *state, u32 *n, u32 *d) { u8 BERRegs[3]; u8 Scale; *n = 0; *d = 1; readregst(state, 0x10, 0x62, BERRegs, 3); readregst(state, 0x10, 0x60, &Scale, 1); Scale &= 0x1F; if (BERRegs[0] & 0x80) { state->LastBERNumerator = (((u32) BERRegs[0] & 0x3F) << 16) | (((u32) BERRegs[1]) << 8) | BERRegs[2]; state->LastBERDenominator = 1632 << Scale; if (state->LastBERNumerator < 256 && Scale < state->BERScaleMax) { writebitst(state, 0x10, 0x60, Scale + 1, 0x1F); } else if (state->LastBERNumerator > 512 && Scale > 11) writebitst(state, 0x10, 0x60, Scale - 1, 0x1F); } *n = state->LastBERNumerator; *d = state->LastBERDenominator; return 0; } static int get_ber_t2(struct cxd_state *state, u32 *n, u32 *d) { u8 BERRegs[4]; u8 Scale; u8 FECType; u8 CodeRate; static const u32 nBCHBitsLookup[2][8] = { /* R1_2 R3_5 R2_3 R3_4 R4_5 R5_6 R1_3 R2_5 */ {7200, 9720, 10800, 11880, 12600, 13320, 5400, 6480}, /* 16K FEC */ {32400, 38880, 43200, 48600, 51840, 54000, 21600, 25920} /* 64k FEC */ }; *n = 0; *d = 1; freeze_regst(state); readregst_unlocked(state, 0x24, 0x40, BERRegs, 4); readregst_unlocked(state, 0x22, 0x5e, &FECType, 1); readregst_unlocked(state, 0x22, 0x5b, &CodeRate, 1); FECType &= 0x03; CodeRate &= 0x07; unfreeze_regst(state); if (FECType > 1) return 0; readregst(state, 0x20, 0x72, &Scale, 1); Scale &= 0x0F; if (BERRegs[0] & 0x01) { state->LastBERNumerator = (((u32) BERRegs[1] & 0x3F) << 16) | (((u32) BERRegs[2]) << 8) | BERRegs[3]; state->LastBERDenominator = nBCHBitsLookup[FECType][CodeRate] << Scale; if (state->LastBERNumerator < 256 && Scale < state->BERScaleMax) { writebitst(state, 0x20, 0x72, Scale + 1, 0x0F); } else if (state->LastBERNumerator > 512 && Scale > 8) writebitst(state, 0x20, 0x72, Scale - 1, 0x0F); } *n = state->LastBERNumerator; *d = state->LastBERDenominator; return 0; } static int get_ber_c(struct cxd_state *state, u32 *n, u32 *d) { u8 BERRegs[3]; u8 Scale; *n = 0; *d = 1; readregst(state, 0x40, 0x62, BERRegs, 3); readregst(state, 0x40, 0x60, &Scale, 1); Scale &= 0x1F; if (BERRegs[0] & 0x80) { state->LastBERNumerator = (((u32) BERRegs[0] & 0x3F) << 16) | (((u32) BERRegs[1]) << 8) | BERRegs[2]; state->LastBERDenominator = 1632 << Scale; if (state->LastBERNumerator < 256 && Scale < state->BERScaleMax) { writebitst(state, 0x40, 0x60, Scale + 1, 0x1F); } else if (state->LastBERNumerator > 512 && Scale > 11) writebitst(state, 0x40, 0x60, Scale - 1, 0x1F); } *n = state->LastBERNumerator; *d = state->LastBERDenominator; return 0; } static int get_ber_c2(struct cxd_state *state, u32 *n, u32 *d) { *n = 0; *d = 1; return 0; } static int get_ber_it(struct cxd_state *state, u32 *n, u32 *d) { *n = 0; *d = 1; return 0; } static int read_ber(struct dvb_frontend *fe, u32 *ber) { struct cxd_state *state = fe->demodulator_priv; struct dtv_frontend_properties *p = &fe->dtv_property_cache; u32 n = 0, d = 1; int s = 0; *ber = 0; switch (state->state) { case ActiveT: s = get_ber_t(state, &n, &d); break; case ActiveT2: s = get_ber_t2(state, &n, &d); break; case ActiveC: s = get_ber_c(state, &n, &d); break; case ActiveC2: s = get_ber_c2(state, &n, &d); break; case ActiveIT: s = get_ber_it(state, &n, &d); break; default: break; } if (s) return s; p->pre_bit_error.len = 1; p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; p->pre_bit_error.stat[0].uvalue = n; p->pre_bit_count.len = 1; p->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; p->pre_bit_count.stat[0].uvalue = d; if (d) *ber = (n * 1000) / d; return 0; } static int read_signal_strength(struct dvb_frontend *fe, u16 *strength) { if (fe->ops.tuner_ops.get_rf_strength) fe->ops.tuner_ops.get_rf_strength(fe, strength); else *strength = 0; return 0; } #if 0 +NTSTATUS CCXD2843ER::GetT2PLPIds(DD_T2_PLPIDS* pT2_PLPIDS) { NTSTATUS status = STATUS_SUCCESS; - *pReturned = 0; + if( m_DemodState != ActiveT2 ) return STATUS_NOT_IMPLEMENTED; - if( m_LastLockStatus < TSLock || m_LastLockStatus == Unlock ) return status; + if( m_LastLockStatus < TSLock ) return status; do { + u8 tmp; + CHK_ERROR(FreezeRegsT()); + CHK_ERROR(ReadRegT(0x20,0x5C,&tmp)); // OFDM Info + + if( tmp & 0x20 ) pT2_PLPIDS->Flags |= DD_T2_PLPIDS_FEF; + if( m_T2Profile == T2P_Lite ) pT2_PLPIDS->Flags |= DD_T2_PLPIDS_LITE; + + CHK_ERROR(ReadRegT(0x22,0x54,&tmp)); + pT2_PLPIDS->PLPID = tmp; + + CHK_ERROR(ReadRegT(0x22,0x54 + 19 + 13,&tmp)); // Interval + if( tmp > 0 ) + { + CHK_ERROR(ReadRegT(0x22,0x54 + 19,&tmp)); + pT2_PLPIDS->CommonPLPID = tmp; + } + u8 nPids = 0; CHK_ERROR(ReadRegT(0x22,0x7F,&nPids)); - pValues[0] = nPids; - if( nPids >= nValues ) nPids = nValues - 1; + pT2_PLPIDS->NumPLPS = nPids; + CHK_ERROR(ReadRegT(0x22,0x80,&pT2_PLPIDS->PLPList[0], nPids > 128 ? 128 : nPids)); - CHK_ERROR(ReadRegT(0x22,0x80,&pValues[1], nPids > 128 ? 128 : nPids)); - if( nPids > 128 ) { - CHK_ERROR(ReadRegT(0x23,0x10,&pValues[129], nPids - 128)); + CHK_ERROR(ReadRegT(0x23,0x10,&pT2_PLPIDS->PLPList[128], nPids - 128)); } - *pReturned = nPids + 1; + } while(0); UnFreezeRegsT(); static void GetPLPIds(struct cxd_state *state, u32 nValues, u8 *Values, u32 *Returned) { u8 nPids = 0, tmp; *Returned = 0; if (state->state != ActiveT2) return; if (state->last_status != 0x1f) return; freeze_regst(state); readregst_unlocked(state, 0x22, 0x7F, &nPids, 1); Values[0] = nPids; if (nPids >= nValues) nPids = nValues - 1; readregst_unlocked(state, 0x22, 0x80, &Values[1], nPids > 128 ? 128 : nPids); if (nPids > 128) readregst_unlocked(state, 0x23, 0x10, &Values[129], nPids - 128); *Returned = nPids + 1; unfreeze_regst(state); } #endif static void GetSignalToNoiseIT(struct cxd_state *state, u32 *SignalToNoise) { u8 Data[2]; u32 reg; *SignalToNoise = 0; freeze_regst(state); readregst_unlocked(state, 0x60, 0x28, Data, sizeof(Data)); unfreeze_regst(state); reg = (Data[0] << 8) | Data[1]; if (reg == 0) return; if (reg > 51441) reg = 51441; if (state->bw == 8) { if (reg > 1143) reg = 1143; *SignalToNoise = (Log10x100(reg) - Log10x100(1200 - reg)) + 220; } else *SignalToNoise = Log10x100(reg) - 90; } static void GetSignalToNoiseC2(struct cxd_state *state, u32 *SignalToNoise) { u8 Data[2]; u32 reg; *SignalToNoise = 0; freeze_regst(state); readregst_unlocked(state, 0x20, 0x28, Data, sizeof(Data)); unfreeze_regst(state); reg = (Data[0] << 8) | Data[1]; if (reg == 0) return; if (reg > 51441) reg = 51441; *SignalToNoise = (Log10x100(reg) - Log10x100(55000 - reg)) + 384; } static void GetSignalToNoiseT2(struct cxd_state *state, u32 *SignalToNoise) { u8 Data[2]; u32 reg; *SignalToNoise = 0; freeze_regst(state); readregst_unlocked(state, 0x20, 0x28, Data, sizeof(Data)); unfreeze_regst(state); reg = (Data[0] << 8) | Data[1]; if (reg == 0) return; if (reg > 10876) reg = 10876; *SignalToNoise = (Log10x100(reg) - Log10x100(12600 - reg)) + 320; } static void GetSignalToNoiseT(struct cxd_state *state, u32 *SignalToNoise) { u8 Data[2]; u32 reg; *SignalToNoise = 0; freeze_regst(state); readregst_unlocked(state, 0x10, 0x28, Data, sizeof(Data)); unfreeze_regst(state); reg = (Data[0] << 8) | Data[1]; if (reg == 0) return; if (reg > 4996) reg = 4996; *SignalToNoise = (Log10x100(reg) - Log10x100(5350 - reg)) + 285; } static void GetSignalToNoiseC(struct cxd_state *state, u32 *SignalToNoise) { u8 Data[2]; u8 Constellation = 0; u32 reg; *SignalToNoise = 0; freeze_regst(state); readregst_unlocked(state, 0x40, 0x19, &Constellation, 1); readregst_unlocked(state, 0x40, 0x4C, Data, sizeof(Data)); unfreeze_regst(state); reg = ((u32)(Data[0] & 0x1F) << 8) | (Data[1]); if (reg == 0) return; switch (Constellation & 0x07) { case 0: /* QAM 16 */ case 2: /* QAM 64 */ case 4: /* QAM 256 */ if (reg < 126) reg = 126; *SignalToNoise = ((439 - Log10x100(reg)) * 2134 + 500) / 1000; break; case 1: /* QAM 32 */ case 3: /* QAM 128 */ if (reg < 69) reg = 69; *SignalToNoise = ((432 - Log10x100(reg)) * 2015 + 500) / 1000; break; } } static int read_snr(struct dvb_frontend *fe, u16 *snr) { struct cxd_state *state = fe->demodulator_priv; struct dtv_frontend_properties *p = &fe->dtv_property_cache; u32 SNR = 0; *snr = 0; if (state->last_status != 0x1f) return 0; switch (state->state) { case ActiveC: GetSignalToNoiseC(state, &SNR); break; case ActiveC2: GetSignalToNoiseC2(state, &SNR); break; case ActiveT: GetSignalToNoiseT(state, &SNR); break; case ActiveT2: GetSignalToNoiseT2(state, &SNR); break; case ActiveIT: GetSignalToNoiseIT(state, &SNR); break; default: break; } *snr = SNR; p->cnr.len = 1; p->cnr.stat[0].scale = FE_SCALE_DECIBEL; p->cnr.stat[0].svalue = 10 * (s64) SNR; return 0; } static int read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) { *ucblocks = 0; return 0; } static int tune(struct dvb_frontend *fe, bool re_tune, unsigned int mode_flags, unsigned int *delay, enum fe_status *status) { struct cxd_state *state = fe->demodulator_priv; int r; if (re_tune) { r = set_parameters(fe); if (r) return r; state->tune_time = jiffies; } r = read_status(fe, status); if (r) return r; if (*status & FE_HAS_LOCK) { *delay = HZ; return 0; } return 0; } static enum dvbfe_search search(struct dvb_frontend *fe) { int r; u32 loops = 20, i; enum fe_status status; r = set_parameters(fe); for (i = 0; i < loops; i++) { msleep(50); r = read_status(fe, &status); if (r) return DVBFE_ALGO_SEARCH_ERROR; if (status & FE_HAS_LOCK) break; } if (status & FE_HAS_LOCK) return DVBFE_ALGO_SEARCH_SUCCESS; else return DVBFE_ALGO_SEARCH_AGAIN; } static enum dvbfe_algo get_algo(struct dvb_frontend *fe) { return DVBFE_ALGO_HW; } static int get_fe_t2(struct cxd_state *state, struct dtv_frontend_properties *p) { //struct dvb_frontend *fe = &state->frontend; u8 ofdm[5], modcod[2]; freeze_regst(state); readregst_unlocked(state, 0x20, 0x5c, ofdm, 5); readregst_unlocked(state, 0x22, 0x5b, modcod, 2); unfreeze_regst(state); switch (modcod[0] & 0x07) { case 0: p->fec_inner = FEC_1_2; break; case 1: p->fec_inner = FEC_3_5; break; case 2: p->fec_inner = FEC_2_3; break; case 3: p->fec_inner = FEC_3_4; break; case 4: p->fec_inner = FEC_4_5; break; case 5: p->fec_inner = FEC_5_6; break; case 6: p->fec_inner = FEC_1_3; break; case 7: p->fec_inner = FEC_2_5; break; } switch (modcod[1] & 0x07) { case 0: p->modulation = QPSK; break; case 1: p->modulation = QAM_16; break; case 2: p->modulation = QAM_64; break; case 3: p->modulation = QAM_256; break; } switch (ofdm[0] & 0x07) { case 0: p->transmission_mode = TRANSMISSION_MODE_2K; break; case 1: p->transmission_mode = TRANSMISSION_MODE_8K; break; case 2: p->transmission_mode = TRANSMISSION_MODE_4K; break; case 3: p->transmission_mode = TRANSMISSION_MODE_1K; break; case 4: p->transmission_mode = TRANSMISSION_MODE_16K; break; case 5: p->transmission_mode = TRANSMISSION_MODE_32K; break; } switch ((ofdm[1] >> 4) & 0x07) { case 0: p->guard_interval = GUARD_INTERVAL_1_32; break; case 1: p->guard_interval = GUARD_INTERVAL_1_16; break; case 2: p->guard_interval = GUARD_INTERVAL_1_8; break; case 3: p->guard_interval = GUARD_INTERVAL_1_4; break; case 4: p->guard_interval = GUARD_INTERVAL_1_128; break; case 5: p->guard_interval = GUARD_INTERVAL_19_128; break; case 6: p->guard_interval = GUARD_INTERVAL_19_256; break; } return 0; } static int get_fe_t(struct cxd_state *state, struct dtv_frontend_properties *p) { //struct dvb_frontend *fe = &state->frontend; u8 tps[7]; read_tps(state, tps); /* TPSData[0] [7:6] CNST[1:0] TPSData[0] [5:3] HIER[2:0] TPSData[0] [2:0] HRATE[2:0] */ switch ((tps[0] >> 6) & 0x03) { case 0: p->modulation = QPSK; break; case 1: p->modulation = QAM_16; break; case 2: p->modulation = QAM_64; break; } switch ((tps[0] >> 3) & 0x07) { case 0: p->hierarchy = HIERARCHY_NONE; break; case 1: p->hierarchy = HIERARCHY_1; break; case 2: p->hierarchy = HIERARCHY_2; break; case 3: p->hierarchy = HIERARCHY_4; break; } switch ((tps[0] >> 0) & 0x07) { case 0: p->code_rate_HP = FEC_1_2; break; case 1: p->code_rate_HP = FEC_2_3; break; case 2: p->code_rate_HP = FEC_3_4; break; case 3: p->code_rate_HP = FEC_5_6; break; case 4: p->code_rate_HP = FEC_7_8; break; } /* TPSData[1] [7:5] LRATE[2:0] TPSData[1] [4:3] GI[1:0] TPSData[1] [2:1] MODE[1:0] */ switch ((tps[1] >> 5) & 0x07) { case 0: p->code_rate_LP = FEC_1_2; break; case 1: p->code_rate_LP = FEC_2_3; break; case 2: p->code_rate_LP = FEC_3_4; break; case 3: p->code_rate_LP = FEC_5_6; break; case 4: p->code_rate_LP = FEC_7_8; break; } switch ((tps[1] >> 3) & 0x03) { case 0: p->guard_interval = GUARD_INTERVAL_1_32; break; case 1: p->guard_interval = GUARD_INTERVAL_1_16; break; case 2: p->guard_interval = GUARD_INTERVAL_1_8; break; case 3: p->guard_interval = GUARD_INTERVAL_1_4; break; } switch ((tps[1] >> 1) & 0x03) { case 0: p->transmission_mode = TRANSMISSION_MODE_2K; break; case 1: p->transmission_mode = TRANSMISSION_MODE_8K; break; } return 0; } static int get_fe_c(struct cxd_state *state, struct dtv_frontend_properties *p) { //struct dvb_frontend *fe = &state->frontend; u8 qam; freeze_regst(state); readregst_unlocked(state, 0x40, 0x19, &qam, 1); unfreeze_regst(state); p->modulation = 1 + (qam & 0x07); return 0; } static int get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties *p) { struct cxd_state *state = fe->demodulator_priv; if (state->last_status != 0x1f) return 0; switch (state->state) { case ActiveT: get_fe_t(state, p); break; case ActiveT2: get_fe_t2(state, p); break; case ActiveC: get_fe_c(state, p); break; case ActiveC2: break; case ActiveIT: break; default: break; } return 0; } static struct dvb_frontend_ops common_ops_2854 = { .delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT, SYS_DVBT2, SYS_DVBC2, SYS_ISDBT }, .info = { .name = "CXD2854 DVB-C/C2 DVB-T/T2 ISDB-T", .frequency_stepsize_hz = 166667, /* DVB-T only */ .frequency_min_hz = 47000000, /* DVB-T: 47125000 */ .frequency_max_hz = 865000000, /* DVB-C: 862000000 */ .symbol_rate_min = 870000, .symbol_rate_max = 11700000, .caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_QAM_AUTO | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION | FE_CAN_MULTISTREAM }, .release = release, .sleep = sleep, .i2c_gate_ctrl = gate_ctrl, .set_frontend = set_parameters, .get_tune_settings = get_tune_settings, .read_status = read_status, .read_ber = read_ber, .read_signal_strength = read_signal_strength, .read_snr = read_snr, .read_ucblocks = read_ucblocks, .get_frontend = get_frontend, }; static struct dvb_frontend_ops common_ops_2843 = { .delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT, SYS_DVBT2, SYS_DVBC2 }, .info = { .name = "CXD2843 DVB-C/C2 DVB-T/T2", .frequency_stepsize_hz = 166667, /* DVB-T only */ .frequency_min_hz = 47000000, /* DVB-T: 47125000 */ .frequency_max_hz = 865000000, /* DVB-C: 862000000 */ .symbol_rate_min = 870000, .symbol_rate_max = 11700000, .caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_QAM_AUTO | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION | FE_CAN_MULTISTREAM }, .release = release, .sleep = sleep, .i2c_gate_ctrl = gate_ctrl, .set_frontend = set_parameters, .get_tune_settings = get_tune_settings, .read_status = read_status, .read_ber = read_ber, .read_signal_strength = read_signal_strength, .read_snr = read_snr, .read_ucblocks = read_ucblocks, .get_frontend = get_frontend, #ifdef USE_ALGO .get_frontend_algo = get_algo, .search = search, .tune = tune, #endif }; static struct dvb_frontend_ops common_ops_2837 = { .delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT, SYS_DVBT2 }, .info = { .name = "CXD2837 DVB-C DVB-T/T2", .frequency_stepsize_hz = 166667, /* DVB-T only */ .frequency_min_hz = 47000000, /* DVB-T: 47125000 */ .frequency_max_hz = 865000000, /* DVB-C: 862000000 */ .symbol_rate_min = 870000, .symbol_rate_max = 11700000, .caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_QAM_AUTO | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION | FE_CAN_MULTISTREAM }, .release = release, .sleep = sleep, .i2c_gate_ctrl = gate_ctrl, .set_frontend = set_parameters, .get_tune_settings = get_tune_settings, .read_status = read_status, .read_ber = read_ber, .read_signal_strength = read_signal_strength, .read_snr = read_snr, .read_ucblocks = read_ucblocks, .get_frontend = get_frontend, #ifdef USE_ALGO .get_frontend_algo = get_algo, .search = search, .tune = tune, #endif }; static struct dvb_frontend_ops common_ops_2838 = { .delsys = { SYS_ISDBT }, .info = { .name = "CXD2838 ISDB-T", .frequency_stepsize_hz = 166667, .frequency_min_hz = 47000000, .frequency_max_hz = 865000000, .symbol_rate_min = 870000, .symbol_rate_max = 11700000, .caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION }, .release = release, .sleep = sleep, .i2c_gate_ctrl = gate_ctrl, .set_frontend = set_parameters, .get_tune_settings = get_tune_settings, .read_status = read_status, .read_ber = read_ber, .read_signal_strength = read_signal_strength, .read_snr = read_snr, .read_ucblocks = read_ucblocks, #ifdef USE_ALGO .get_frontend_algo = get_algo, .search = search, .tune = tune, #endif }; static int probe(struct cxd_state *state) { u8 ChipID = 0x00; int status; status = readregst(state, 0x00, 0xFD, &ChipID, 1); if (status) status = readregsx(state, 0x00, 0xFD, &ChipID, 1); if (status) return status; printk("ChipID = %02X\n", ChipID); switch (ChipID) { case 0xa4: state->type = CXD2843; memcpy(&state->frontend.ops, &common_ops_2843, sizeof(struct dvb_frontend_ops)); break; case 0xb1: state->type = CXD2837; memcpy(&state->frontend.ops, &common_ops_2837, sizeof(struct dvb_frontend_ops)); break; case 0xb0: state->type = CXD2838; memcpy(&state->frontend.ops, &common_ops_2838, sizeof(struct dvb_frontend_ops)); break; case 0xc1: state->type = CXD2854; memcpy(&state->frontend.ops, &common_ops_2854, sizeof(struct dvb_frontend_ops)); state->is2k14 = 1; break; default: return -1; } state->frontend.demodulator_priv = state; return 0; } struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c, struct cxd2843_cfg *cfg) { struct cxd_state *state = NULL; pr_info("attach\n"); state = kzalloc(sizeof(struct cxd_state), GFP_KERNEL); if (!state) return NULL; state->i2c = i2c; init_state(state, cfg); if (probe(state) == 0) { init(state); return &state->frontend; } pr_err("cxd2843: not found\n"); kfree(state); return NULL; } EXPORT_SYMBOL(cxd2843_attach); MODULE_DESCRIPTION("CXD2843/37/38 driver"); MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel"); MODULE_LICENSE("GPL v2");