From 1b0e822b070c9bbfc7746429212a66dbc97ba054 Mon Sep 17 00:00:00 2001 From: Ralph Metzler Date: Tue, 22 Mar 2016 22:18:13 +0100 Subject: [PATCH] more status API support --- frontends/cxd2843.c | 19 ++- frontends/mxl5xx.c | 139 ++++++++++++++++- frontends/stv0910.c | 112 +++++++++++++- frontends/stv6111.c | 356 ++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 604 insertions(+), 22 deletions(-) diff --git a/frontends/cxd2843.c b/frontends/cxd2843.c index d0e2d23..7ec11ee 100644 --- a/frontends/cxd2843.c +++ b/frontends/cxd2843.c @@ -1457,6 +1457,7 @@ static int get_ber_it(struct cxd_state *state, u32 *n, u32 *d) 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, d; int s = 0; @@ -1482,7 +1483,15 @@ static int read_ber(struct dvb_frontend *fe, u32 *ber) } 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; } @@ -1585,7 +1594,7 @@ static void GetSignalToNoiseIT(struct cxd_state *state, u32 *SignalToNoise) reg = (Data[0] << 8) | Data[1]; if (reg > 51441) reg = 51441; - + if (state->bw == 8) { if (reg > 1143) reg = 1143; @@ -1681,6 +1690,7 @@ static void GetSignalToNoiseC(struct cxd_state *state, u32 *SignalToNoise) 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; @@ -1707,6 +1717,9 @@ static int read_snr(struct dvb_frontend *fe, u16 *snr) break; } *snr = SNR; + p->cnr.len = 1; + p->cnr.stat[0].scale = FE_SCALE_DECIBEL; + p->cnr.stat[0].uvalue = 10 * (s64) SNR; return 0; } @@ -1878,7 +1891,7 @@ static int get_fe_c(struct cxd_state *state) freeze_regst(state); readregst_unlocked(state, 0x40, 0x19, &qam, 1); unfreeze_regst(state); - p->modulation = qam & 0x07; + p->modulation = 1 + (qam & 0x07); return 0; } diff --git a/frontends/mxl5xx.c b/frontends/mxl5xx.c index 9f04b35..7148c64 100644 --- a/frontends/mxl5xx.c +++ b/frontends/mxl5xx.c @@ -447,6 +447,18 @@ static int CfgDemodAbortTune(struct mxl *state) return send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE, &cmdBuff[0]); } +static int reset_fec_counter(struct mxl *state) +{ + MXL_HYDRA_DEMOD_ABORT_TUNE_T abortTuneCmd; + u32 demodIndex = (u32) state->demod; + u8 cmdSize = sizeof(u32); + u8 cmdBuff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN]; + + BUILD_HYDRA_CMD(MXL_HYDRA_DEMOD_RESET_FEC_COUNTER_CMD, + MXL_CMD_WRITE, cmdSize, &demodIndex, cmdBuff); + return send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE, &cmdBuff[0]); +} + static int send_master_cmd(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd) { @@ -620,8 +632,52 @@ static int read_snr(struct dvb_frontend *fe, u16 *snr) static int read_ber(struct dvb_frontend *fe, u32 *ber) { + struct mxl *state = fe->demodulator_priv; + struct dtv_frontend_properties *p = &fe->dtv_property_cache; + u32 reg[8], reg2[4]; + int stat; + *ber = 0; - + mutex_lock(&state->base->status_lock); + HYDRA_DEMOD_STATUS_LOCK(state, state->demod); + stat = read_register_block(state, + (HYDRA_DMD_DVBS2_CRC_ERRORS_ADDR_OFFSET + + HYDRA_DMD_STATUS_OFFSET(state->demod)), + (7 * sizeof(u32)), + (u8 *) ®[0]); + stat = read_register_block(state, + (HYDRA_DMD_DVBS_1ST_CORR_RS_ERRORS_ADDR_OFFSET + + HYDRA_DMD_STATUS_OFFSET(state->demod)), + (4 * sizeof(u32)), + (u8 *) ®2[0]); + HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod); + mutex_unlock(&state->base->status_lock); + + + switch (p->delivery_system) { + case SYS_DSS: + break; + case SYS_DVBS: + p->pre_bit_error.len = 1; + p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; + p->pre_bit_error.stat[0].uvalue = reg[5]; + p->pre_bit_count.len = 1; + p->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; + p->pre_bit_count.stat[0].uvalue = reg[6] * 188 * 8; + break; + case SYS_DVBS2: + break; + default: + break; + } + pr_info("mxl5xx: ber %08x %08x %08x %08x %08x %08x %08x\n", + reg[0], reg[1], reg[2], reg[3], reg[4], reg[5], reg[6]); + pr_info("mxl5xx: ber2 %08x %08x %08x %08x\n", + reg[0], reg[1], reg[2], reg[3]); + //pre_bit_error, pre_bit_count + //post_bit_error, post_bit_count; + //block_error block_count; + //reset_fec_counter(state); return 0; } @@ -654,24 +710,99 @@ static int read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) static int get_stats(struct dvb_frontend *fe) { u16 val; + u32 val32; read_signal_strength(fe, &val); read_snr(fe, &val); + read_ber(fe, &val32); return 0; } +static fe_code_rate_t conv_fec(MXL_HYDRA_FEC_E fec) +{ + enum fe_code_rate fec2fec[11] = { + FEC_NONE, FEC_1_2, FEC_3_5, FEC_2_3, + FEC_3_4, FEC_4_5, FEC_5_6, FEC_6_7, + FEC_7_8, FEC_8_9, FEC_9_10 + }; + + if (fec > MXL_HYDRA_FEC_9_10) + return FEC_NONE; + return fec2fec[fec]; +} static int get_frontend(struct dvb_frontend *fe) { - //struct mxl *state = fe->demodulator_priv; + struct mxl *state = fe->demodulator_priv; struct dtv_frontend_properties *p = &fe->dtv_property_cache; + u32 regData[MXL_DEMOD_CHAN_PARAMS_BUFF_SIZE]; + u32 freq; + int stat; + mutex_lock(&state->base->status_lock); + HYDRA_DEMOD_STATUS_LOCK(state, state->demod); + stat = read_register_block(state, + (HYDRA_DMD_STANDARD_ADDR_OFFSET + + HYDRA_DMD_STATUS_OFFSET(state->demod)), + (MXL_DEMOD_CHAN_PARAMS_BUFF_SIZE * 4), // 25 * 4 bytes + (u8 *) ®Data[0]); + // read demod channel parameters + stat = read_register_block(state, + (HYDRA_DMD_STATUS_CENTER_FREQ_IN_KHZ_ADDR + + HYDRA_DMD_STATUS_OFFSET(state->demod)), + (4), // 4 bytes + (u8 *) &freq); + HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod); + mutex_unlock(&state->base->status_lock); + + pr_info("mxl5xx: freq=%u delsys=%u srate=%u\n", + freq * 1000, regData[DMD_STANDARD_ADDR], + regData[DMD_SYMBOL_RATE_ADDR]); + p->symbol_rate = regData[DMD_SYMBOL_RATE_ADDR]; + p->frequency = freq; + //p->delivery_system = (MXL_HYDRA_BCAST_STD_E )regData[DMD_STANDARD_ADDR]; + //p->inversion = (MXL_HYDRA_SPECTRUM_E )regData[DMD_SPECTRUM_INVERSION_ADDR]; + //freqSearchRangeKHz = (regData[DMD_FREQ_SEARCH_RANGE_IN_KHZ_ADDR]); + + p->fec_inner = conv_fec(regData[DMD_FEC_CODE_RATE_ADDR]); switch (p->delivery_system) { case SYS_DSS: break; - case SYS_DVBS: - break; case SYS_DVBS2: + switch ((MXL_HYDRA_PILOTS_E ) regData[DMD_DVBS2_PILOT_ON_OFF_ADDR]) { + case MXL_HYDRA_PILOTS_OFF: + p->pilot = PILOT_OFF; + break; + case MXL_HYDRA_PILOTS_ON: + p->pilot = PILOT_ON; + break; + default: + break; + } + case SYS_DVBS: + switch ((MXL_HYDRA_MODULATION_E) regData[DMD_MODULATION_SCHEME_ADDR]) { + case MXL_HYDRA_MOD_QPSK: + p->modulation = QPSK; + break; + case MXL_HYDRA_MOD_8PSK: + p->modulation = PSK_8; + break; + default: + break; + } + switch ((MXL_HYDRA_ROLLOFF_E) regData[DMD_SPECTRUM_ROLL_OFF_ADDR]) { + case MXL_HYDRA_ROLLOFF_0_20: + p->rolloff = ROLLOFF_20; + break; + case MXL_HYDRA_ROLLOFF_0_35: + p->rolloff = ROLLOFF_35; + break; + case MXL_HYDRA_ROLLOFF_0_25: + p->rolloff = ROLLOFF_25; + break; + default: + break; + } break; default: return -EINVAL; diff --git a/frontends/stv0910.c b/frontends/stv0910.c index aba0dff..2fba226 100644 --- a/frontends/stv0910.c +++ b/frontends/stv0910.c @@ -1039,15 +1039,40 @@ static int set_parameters(struct dvb_frontend *fe) return stat; } +static int get_frontend(struct dvb_frontend *fe) +{ + struct stv *state = fe->demodulator_priv; + struct dtv_frontend_properties *p = &fe->dtv_property_cache; + + + return 0; +} + + +static int read_snr(struct dvb_frontend *fe, u16 *snr); +static int read_signal_strength(struct dvb_frontend *fe, u16 *strength); +static int read_ber(struct dvb_frontend *fe, u32 *ber); static int read_status(struct dvb_frontend *fe, fe_status_t *status) { struct stv *state = fe->demodulator_priv; + struct dtv_frontend_properties *p = &fe->dtv_property_cache; u8 DmdState = 0; u8 DStatus = 0; enum ReceiveMode CurReceiveMode = Mode_None; u32 FECLock = 0; + u16 val; + u32 ber; + + read_signal_strength(fe, &val); + read_snr(fe, &val); + p->cnr.len = 1; + p->cnr.stat[0].scale = FE_SCALE_DECIBEL; + p->cnr.stat[0].uvalue = (s64) (s16) val; + + read_ber(fe, &ber); + read_reg(state, RSTV0910_P2_DMDSTATE + state->regoff, &DmdState); if (DmdState & 0x40) { @@ -1274,6 +1299,7 @@ static int read_snr(struct dvb_frontend *fe, u16 *snr) static int read_ber(struct dvb_frontend *fe, u32 *ber) { struct stv *state = fe->demodulator_priv; + struct dtv_frontend_properties *p = &fe->dtv_property_cache; u32 n, d; GetBitErrorRate(state, &n, &d); @@ -1281,18 +1307,97 @@ static int read_ber(struct dvb_frontend *fe, u32 *ber) *ber = n / d; else *ber = 0; + + 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; return 0; } +static s32 Log10x100(u32 x) +{ + static u32 LookupTable[100] = { + 101157945, 103514217, 105925373, 108392691, 110917482, + 113501082, 116144861, 118850223, 121618600, 124451461, + 127350308, 130316678, 133352143, 136458314, 139636836, + 142889396, 146217717, 149623566, 153108746, 156675107, + 160324539, 164058977, 167880402, 171790839, 175792361, + 179887092, 184077200, 188364909, 192752491, 197242274, + 201836636, 206538016, 211348904, 216271852, 221309471, + 226464431, 231739465, 237137371, 242661010, 248313311, + 254097271, 260015956, 266072506, 272270131, 278612117, + 285101827, 291742701, 298538262, 305492111, 312607937, + 319889511, 327340695, 334965439, 342767787, 350751874, + 358921935, 367282300, 375837404, 384591782, 393550075, + 402717034, 412097519, 421696503, 431519077, 441570447, + 451855944, 462381021, 473151259, 484172368, 495450191, + 506990708, 518800039, 530884444, 543250331, 555904257, + 568852931, 582103218, 595662144, 609536897, 623734835, + 638263486, 653130553, 668343918, 683911647, 699841996, + 716143410, 732824533, 749894209, 767361489, 785235635, + 803526122, 822242650, 841395142, 860993752, 881048873, + 901571138, 922571427, 944060876, 966050879, 988553095, + }; + s32 y; + int i; + + if (x == 0) + return 0; + y = 800; + if (x >= 1000000000) { + x /= 10; + y += 100; + } + + while (x < 100000000) { + x *= 10; + y -= 100; + } + i = 0; + while (i < 100 && x > LookupTable[i]) + i += 1; + y += i; + return y; +} + static int read_signal_strength(struct dvb_frontend *fe, u16 *strength) { struct stv *state = fe->demodulator_priv; + struct dtv_frontend_properties *p = &fe->dtv_property_cache; u8 Agc1, Agc0; + u8 Reg[2]; + u32 pBBGain; + s32 Power = 0; + int i; - read_reg(state, RSTV0910_P2_AGCIQIN1 + state->regoff, &Agc1); - read_reg(state, RSTV0910_P2_AGCIQIN0 + state->regoff, &Agc0); + read_regs(state, RSTV0910_P2_AGCIQIN1 + state->regoff, Reg, 2); + //KdPrintEx((MSG_INFO "_%d " __FUNCTION__ " AGCIQIN1 = %02x%02x\n",m_Instance,Reg[0],Reg[1])); + + *strength = (((u32) Reg[0]) << 8) | Reg[1]; + + for (i = 0; i < 5; i += 1) { + read_regs(state, RSTV0910_P2_POWERI + state->regoff, Reg, 2); + Power += (u32) Reg[0] * (u32) Reg[0] + (u32) Reg[1] * (u32) Reg[1]; + msleep(3); + } + Power /= 5; + + pBBGain = (465 - Log10x100(Power)); + + if (fe->ops.tuner_ops.get_rf_strength) + fe->ops.tuner_ops.get_rf_strength(fe, strength); + else + *strength = 0; + + *strength += pBBGain * 10; + + p->strength.len = 1; + p->strength.stat[0].scale = FE_SCALE_DECIBEL; + p->strength.stat[0].uvalue = 10 * (s64) (s16) *strength - 108750; - *strength = ((255 - Agc1) * 3300) / 256; return 0; } @@ -1324,6 +1429,7 @@ static struct dvb_frontend_ops stv0910_ops = { .release = release, .i2c_gate_ctrl = gate_ctrl, .get_frontend_algo = get_algo, + .get_frontend = get_frontend, .tune = tune, .read_status = read_status, .set_tone = set_tone, diff --git a/frontends/stv6111.c b/frontends/stv6111.c index 691b8b9..984e6eb 100644 --- a/frontends/stv6111.c +++ b/frontends/stv6111.c @@ -50,6 +50,7 @@ struct stv { u8 reg[11]; u32 ref_freq; + u32 Frequency; }; static int i2c_read(struct i2c_adapter *adap, @@ -87,14 +88,12 @@ static int write_regs(struct stv *state, int reg, int len) return i2c_write(state->i2c, state->adr, d, len + 1); } -#if 0 static int write_reg(struct stv *state, u8 reg, u8 val) { u8 d[2] = {reg, val}; return i2c_write(state->i2c, state->adr, d, 2); } -#endif static int read_reg(struct stv *state, u8 reg, u8 *val) { @@ -298,6 +297,8 @@ static int set_lof(struct stv *state, u32 LocalFrequency, u32 CutOffFrequency) } read_reg(state, 0x08, &tmp); + state->Frequency = Frequency; + dump_regs(state); return 0; } @@ -362,21 +363,352 @@ static u32 AGC_Gain[] = { 67000, /* 2.9 */ }; +struct SLookup { + s16 Value; + u16 RegValue; +}; + + +static struct SLookup LNAGain_NF_LookUp[] = { + /*Gain *100dB*/ /*Reg*/ + { 2572 , 0 }, + { 2575 , 1 }, + { 2580 , 2 }, + { 2588 , 3 }, + { 2596 , 4 }, + { 2611 , 5 }, + { 2633 , 6 }, + { 2664 , 7 }, + { 2701 , 8 }, + { 2753 , 9 }, + { 2816 , 10 }, + { 2902 , 11 }, + { 2995 , 12 }, + { 3104 , 13 }, + { 3215 , 14 }, + { 3337 , 15 }, + { 3492 , 16 }, + { 3614 , 17 }, + { 3731 , 18 }, + { 3861 , 19 }, + { 3988 , 20 }, + { 4124 , 21 }, + { 4253 , 22 }, + { 4386 , 23 }, + { 4505 , 24 }, + { 4623 , 25 }, + { 4726 , 26 }, + { 4821 , 27 }, + { 4903 , 28 }, + { 4979 , 29 }, + { 5045 , 30 }, + { 5102 , 31 } +}; + +static struct SLookup LNAGain_IIP3_LookUp[] = { + /*Gain *100dB*/ /*reg*/ + { 1548 , 0 }, + { 1552 , 1 }, + { 1569 , 2 }, + { 1565 , 3 }, + { 1577 , 4 }, + { 1594 , 5 }, + { 1627 , 6 }, + { 1656 , 7 }, + { 1700 , 8 }, + { 1748 , 9 }, + { 1805 , 10 }, + { 1896 , 11 }, + { 1995 , 12 }, + { 2113 , 13 }, + { 2233 , 14 }, + { 2366 , 15 }, + { 2543 , 16 }, + { 2687 , 17 }, + { 2842 , 18 }, + { 2999 , 19 }, + { 3167 , 20 }, + { 3342 , 21 }, + { 3507 , 22 }, + { 3679 , 23 }, + { 3827 , 24 }, + { 3970 , 25 }, + { 4094 , 26 }, + { 4210 , 27 }, + { 4308 , 28 }, + { 4396 , 29 }, + { 4468 , 30 }, + { 4535 , 31 } +}; + +static struct SLookup Gain_RFAGC_LookUp[] = { + /*Gain *100dB*/ /*reg*/ + { 4870 , 0x3000 }, + { 4850 , 0x3C00 }, + { 4800 , 0x4500 }, + { 4750 , 0x4800 }, + { 4700 , 0x4B00 }, + { 4650 , 0x4D00 }, + { 4600 , 0x4F00 }, + { 4550 , 0x5100 }, + { 4500 , 0x5200 }, + { 4420 , 0x5500 }, + { 4316 , 0x5800 }, + { 4200 , 0x5B00 }, + { 4119 , 0x5D00 }, + { 3999 , 0x6000 }, + { 3950 , 0x6100 }, + { 3876 , 0x6300 }, + { 3755 , 0x6600 }, + { 3641 , 0x6900 }, + { 3567 , 0x6B00 }, + { 3425 , 0x6F00 }, + { 3350 , 0x7100 }, + { 3236 , 0x7400 }, + { 3118 , 0x7700 }, + { 3004 , 0x7A00 }, + { 2917 , 0x7C00 }, + { 2776 , 0x7F00 }, + { 2635 , 0x8200 }, + { 2516 , 0x8500 }, + { 2406 , 0x8800 }, + { 2290 , 0x8B00 }, + { 2170 , 0x8E00 }, + { 2073 , 0x9100 }, + { 1949 , 0x9400 }, + { 1836 , 0x9700 }, + { 1712 , 0x9A00 }, + { 1631 , 0x9C00 }, + { 1515 , 0x9F00 }, + { 1400 , 0xA200 }, + { 1323 , 0xA400 }, + { 1203 , 0xA700 }, + { 1091 , 0xAA00 }, + { 1011 , 0xAC00 }, + { 904 , 0xAF00 }, + { 787 , 0xB200 }, + { 685 , 0xB500 }, + { 571 , 0xB800 }, + { 464 , 0xBB00 }, + { 374 , 0xBE00 }, + { 275 , 0xC200 }, + { 181 , 0xC600 }, + { 102 , 0xCC00 }, + { 49 , 0xD900 } +}; + + +// This table is 6 dB too low comapred to the others (probably created with a different BB_MAG setting) +static struct SLookup Gain_Channel_AGC_NF_LookUp[] = { + /*Gain *100dB*/ /*reg*/ + { 7082 , 0x3000 }, + { 7052 , 0x4000 }, + { 7007 , 0x4600 }, + { 6954 , 0x4A00 }, + { 6909 , 0x4D00 }, + { 6833 , 0x5100 }, + { 6753 , 0x5400 }, + { 6659 , 0x5700 }, + { 6561 , 0x5A00 }, + { 6472 , 0x5C00 }, + { 6366 , 0x5F00 }, + { 6259 , 0x6100 }, + { 6151 , 0x6400 }, + { 6026 , 0x6700 }, + { 5920 , 0x6900 }, + { 5835 , 0x6B00 }, + { 5770 , 0x6C00 }, + { 5681 , 0x6E00 }, + { 5596 , 0x7000 }, + { 5503 , 0x7200 }, + { 5429 , 0x7300 }, + { 5319 , 0x7500 }, + { 5220 , 0x7700 }, + { 5111 , 0x7900 }, + { 4983 , 0x7B00 }, + { 4876 , 0x7D00 }, + { 4755 , 0x7F00 }, + { 4635 , 0x8100 }, + { 4499 , 0x8300 }, + { 4405 , 0x8500 }, + { 4323 , 0x8600 }, + { 4233 , 0x8800 }, + { 4156 , 0x8A00 }, + { 4038 , 0x8C00 }, + { 3935 , 0x8E00 }, + { 3823 , 0x9000 }, + { 3712 , 0x9200 }, + { 3601 , 0x9500 }, + { 3511 , 0x9700 }, + { 3413 , 0x9900 }, + { 3309 , 0x9B00 }, + { 3213 , 0x9D00 }, + { 3088 , 0x9F00 }, + { 2992 , 0xA100 }, + { 2878 , 0xA400 }, + { 2769 , 0xA700 }, + { 2645 , 0xAA00 }, + { 2538 , 0xAD00 }, + { 2441 , 0xB000 }, + { 2350 , 0xB600 }, + { 2237 , 0xBA00 }, + { 2137 , 0xBF00 }, + { 2039 , 0xC500 }, + { 1938 , 0xDF00 }, + { 1927 , 0xFF00 } +}; + + +static struct SLookup Gain_Channel_AGC_IIP3_LookUp[] = { + /*Gain *100dB*/ /*reg*/ + { 7070 , 0x3000 }, + { 7028 , 0x4000 }, + { 7019 , 0x4600 }, + { 6900 , 0x4A00 }, + { 6811 , 0x4D00 }, + { 6763 , 0x5100 }, + { 6690 , 0x5400 }, + { 6644 , 0x5700 }, + { 6617 , 0x5A00 }, + { 6598 , 0x5C00 }, + { 6462 , 0x5F00 }, + { 6348 , 0x6100 }, + { 6197 , 0x6400 }, + { 6154 , 0x6700 }, + { 6098 , 0x6900 }, + { 5893 , 0x6B00 }, + { 5812 , 0x6C00 }, + { 5773 , 0x6E00 }, + { 5723 , 0x7000 }, + { 5661 , 0x7200 }, + { 5579 , 0x7300 }, + { 5460 , 0x7500 }, + { 5308 , 0x7700 }, + { 5099 , 0x7900 }, + { 4910 , 0x7B00 }, + { 4800 , 0x7D00 }, + { 4785 , 0x7F00 }, + { 4635 , 0x8100 }, + { 4466 , 0x8300 }, + { 4314 , 0x8500 }, + { 4295 , 0x8600 }, + { 4144 , 0x8800 }, + { 3920 , 0x8A00 }, + { 3889 , 0x8C00 }, + { 3771 , 0x8E00 }, + { 3655 , 0x9000 }, + { 3446 , 0x9200 }, + { 3298 , 0x9500 }, + { 3083 , 0x9700 }, + { 3015 , 0x9900 }, + { 2833 , 0x9B00 }, + { 2746 , 0x9D00 }, + { 2632 , 0x9F00 }, + { 2598 , 0xA100 }, + { 2480 , 0xA400 }, + { 2236 , 0xA700 }, + { 2171 , 0xAA00 }, + { 2060 , 0xAD00 }, + { 1999 , 0xB000 }, + { 1974 , 0xB600 }, + { 1820 , 0xBA00 }, + { 1741 , 0xBF00 }, + { 1655 , 0xC500 }, + { 1444 , 0xDF00 }, + { 1325 , 0xFF00 }, +}; + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +static s32 TableLookup(struct SLookup *Table, int TableSize, u16 RegValue) +{ + s32 Gain; + s32 RegDiff; + int imin = 0; + int imax = TableSize - 1; + int i; + + // Assumes Table[0].RegValue < Table[imax].RegValue + if( RegValue <= Table[0].RegValue ) + Gain = Table[0].Value; + else if( RegValue >= Table[imax].RegValue ) + Gain = Table[imax].Value; + else { + while(imax-imin > 1) { + i = (imax + imin) / 2; + if ((Table[imin].RegValue <= RegValue) && + (RegValue <= Table[i].RegValue) ) + imax = i; + else + imin = i; + } + RegDiff = Table[imax].RegValue - Table[imin].RegValue; + Gain = Table[imin].Value; + if (RegDiff != 0) + Gain += ((s32) (RegValue - Table[imin].RegValue) * + (s32)(Table[imax].Value - Table[imin].Value))/(RegDiff); + } + return Gain; +} + static int get_rf_strength(struct dvb_frontend *fe, u16 *st) { - *st = 0; -#if 0 struct stv *state = fe->tuner_priv; + u16 RFAgc = *st; s32 Gain; - u32 Index = RFAgc / 100; - if (Index >= (sizeof(AGC_Gain) / sizeof(AGC_Gain[0]) - 1)) - Gain = AGC_Gain[sizeof(AGC_Gain) / sizeof(AGC_Gain[0]) - 1]; - else - Gain = AGC_Gain[Index] + - ((AGC_Gain[Index+1] - AGC_Gain[Index]) * - (RFAgc % 100)) / 100; + + if ((state->reg[0x03] & 0x60) == 0 ) { + // RF Mode + // Read AGC ADC + u8 Reg = 0; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + write_reg(state, 0x02, state->reg[0x02] | 0x20); + read_reg(state, 2, &Reg); + if( Reg & 0x20 ) + read_reg(state, 2, &Reg); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + if((state->reg[0x02] & 0x80) == 0) + // NF + Gain = TableLookup(LNAGain_NF_LookUp, + ARRAY_SIZE(LNAGain_NF_LookUp), Reg & 0x1F); + else + // IIP3 + Gain = TableLookup(LNAGain_IIP3_LookUp, + ARRAY_SIZE(LNAGain_IIP3_LookUp), Reg & 0x1F); + Gain += TableLookup(Gain_RFAGC_LookUp, + ARRAY_SIZE(Gain_RFAGC_LookUp), RFAgc); + Gain -= 2400; + } else { + // Channel Mode + if( (state->reg[0x02] & 0x80) == 0 ) { + // NF + Gain = TableLookup(Gain_Channel_AGC_NF_LookUp, + ARRAY_SIZE(Gain_Channel_AGC_NF_LookUp), RFAgc); + Gain += 600; + } else { + // IIP3 + Gain = TableLookup(Gain_Channel_AGC_IIP3_LookUp, + ARRAY_SIZE(Gain_Channel_AGC_IIP3_LookUp), RFAgc); + } + } + + if (state->Frequency > 0) + // Tilt correction ( 0.00016 dB/MHz ) + Gain -= ((((s32)(state->Frequency / 1000) - 1550) * 2) / 12); + + Gain += (s32)( (state->reg[0x01] & 0xC0 ) >> 6 ) * 600 - 1300;// + (BBGain * 10); + + if( Gain < 0 ) + Gain = 0; + else if (Gain > 10000) + Gain = 10000; + *st = Gain; -#endif + return 0; }