| /* | |
| * stv0900_sw.c | |
| * | |
| * Driver for ST STV0900 satellite demodulator IC. | |
| * | |
| * Copyright (C) ST Microelectronics. | |
| * Copyright (C) 2009 NetUP Inc. | |
| * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru> | |
| * | |
| * 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 "stv0900.h" | |
| #include "stv0900_reg.h" | |
| #include "stv0900_priv.h" | |
| s32 shiftx(s32 x, int demod, s32 shift) | |
| { | |
| if (demod == 1) | |
| return x - shift; | |
| return x; | |
| } | |
| int stv0900_check_signal_presence(struct stv0900_internal *intp, | |
| enum fe_stv0900_demod_num demod) | |
| { | |
| s32 carr_offset, | |
| agc2_integr, | |
| max_carrier; | |
| int no_signal = FALSE; | |
| carr_offset = (stv0900_read_reg(intp, CFR2) << 8) | |
| | stv0900_read_reg(intp, CFR1); | |
| carr_offset = ge2comp(carr_offset, 16); | |
| agc2_integr = (stv0900_read_reg(intp, AGC2I1) << 8) | |
| | stv0900_read_reg(intp, AGC2I0); | |
| max_carrier = intp->srch_range[demod] / 1000; | |
| max_carrier += (max_carrier / 10); | |
| max_carrier = 65536 * (max_carrier / 2); | |
| max_carrier /= intp->mclk / 1000; | |
| if (max_carrier > 0x4000) | |
| max_carrier = 0x4000; | |
| if ((agc2_integr > 0x2000) | |
| || (carr_offset > (2 * max_carrier)) | |
| || (carr_offset < (-2 * max_carrier))) | |
| no_signal = TRUE; | |
| return no_signal; | |
| } | |
| static void stv0900_get_sw_loop_params(struct stv0900_internal *intp, | |
| s32 *frequency_inc, s32 *sw_timeout, | |
| s32 *steps, | |
| enum fe_stv0900_demod_num demod) | |
| { | |
| s32 timeout, freq_inc, max_steps, srate, max_carrier; | |
| enum fe_stv0900_search_standard standard; | |
| srate = intp->symbol_rate[demod]; | |
| max_carrier = intp->srch_range[demod] / 1000; | |
| max_carrier += max_carrier / 10; | |
| standard = intp->srch_standard[demod]; | |
| max_carrier = 65536 * (max_carrier / 2); | |
| max_carrier /= intp->mclk / 1000; | |
| if (max_carrier > 0x4000) | |
| max_carrier = 0x4000; | |
| freq_inc = srate; | |
| freq_inc /= intp->mclk >> 10; | |
| freq_inc = freq_inc << 6; | |
| switch (standard) { | |
| case STV0900_SEARCH_DVBS1: | |
| case STV0900_SEARCH_DSS: | |
| freq_inc *= 3; | |
| timeout = 20; | |
| break; | |
| case STV0900_SEARCH_DVBS2: | |
| freq_inc *= 4; | |
| timeout = 25; | |
| break; | |
| case STV0900_AUTO_SEARCH: | |
| default: | |
| freq_inc *= 3; | |
| timeout = 25; | |
| break; | |
| } | |
| freq_inc /= 100; | |
| if ((freq_inc > max_carrier) || (freq_inc < 0)) | |
| freq_inc = max_carrier / 2; | |
| timeout *= 27500; | |
| if (srate > 0) | |
| timeout /= srate / 1000; | |
| if ((timeout > 100) || (timeout < 0)) | |
| timeout = 100; | |
| max_steps = (max_carrier / freq_inc) + 1; | |
| if ((max_steps > 100) || (max_steps < 0)) { | |
| max_steps = 100; | |
| freq_inc = max_carrier / max_steps; | |
| } | |
| *frequency_inc = freq_inc; | |
| *sw_timeout = timeout; | |
| *steps = max_steps; | |
| } | |
| static int stv0900_search_carr_sw_loop(struct stv0900_internal *intp, | |
| s32 FreqIncr, s32 Timeout, int zigzag, | |
| s32 MaxStep, enum fe_stv0900_demod_num demod) | |
| { | |
| int no_signal, | |
| lock = FALSE; | |
| s32 stepCpt, | |
| freqOffset, | |
| max_carrier; | |
| max_carrier = intp->srch_range[demod] / 1000; | |
| max_carrier += (max_carrier / 10); | |
| max_carrier = 65536 * (max_carrier / 2); | |
| max_carrier /= intp->mclk / 1000; | |
| if (max_carrier > 0x4000) | |
| max_carrier = 0x4000; | |
| if (zigzag == TRUE) | |
| freqOffset = 0; | |
| else | |
| freqOffset = -max_carrier + FreqIncr; | |
| stepCpt = 0; | |
| do { | |
| stv0900_write_reg(intp, DMDISTATE, 0x1c); | |
| stv0900_write_reg(intp, CFRINIT1, (freqOffset / 256) & 0xff); | |
| stv0900_write_reg(intp, CFRINIT0, freqOffset & 0xff); | |
| stv0900_write_reg(intp, DMDISTATE, 0x18); | |
| stv0900_write_bits(intp, ALGOSWRST, 1); | |
| if (intp->chip_id == 0x12) { | |
| stv0900_write_bits(intp, RST_HWARE, 1); | |
| stv0900_write_bits(intp, RST_HWARE, 0); | |
| } | |
| if (zigzag == TRUE) { | |
| if (freqOffset >= 0) | |
| freqOffset = -freqOffset - 2 * FreqIncr; | |
| else | |
| freqOffset = -freqOffset; | |
| } else | |
| freqOffset += + 2 * FreqIncr; | |
| stepCpt++; | |
| lock = stv0900_get_demod_lock(intp, demod, Timeout); | |
| no_signal = stv0900_check_signal_presence(intp, demod); | |
| } while ((lock == FALSE) | |
| && (no_signal == FALSE) | |
| && ((freqOffset - FreqIncr) < max_carrier) | |
| && ((freqOffset + FreqIncr) > -max_carrier) | |
| && (stepCpt < MaxStep)); | |
| stv0900_write_bits(intp, ALGOSWRST, 0); | |
| return lock; | |
| } | |
| static int stv0900_sw_algo(struct stv0900_internal *intp, | |
| enum fe_stv0900_demod_num demod) | |
| { | |
| int lock = FALSE, | |
| no_signal, | |
| zigzag; | |
| s32 s2fw, | |
| fqc_inc, | |
| sft_stp_tout, | |
| trial_cntr, | |
| max_steps; | |
| stv0900_get_sw_loop_params(intp, &fqc_inc, &sft_stp_tout, | |
| &max_steps, demod); | |
| switch (intp->srch_standard[demod]) { | |
| case STV0900_SEARCH_DVBS1: | |
| case STV0900_SEARCH_DSS: | |
| if (intp->chip_id >= 0x20) | |
| stv0900_write_reg(intp, CARFREQ, 0x3b); | |
| else | |
| stv0900_write_reg(intp, CARFREQ, 0xef); | |
| stv0900_write_reg(intp, DMDCFGMD, 0x49); | |
| zigzag = FALSE; | |
| break; | |
| case STV0900_SEARCH_DVBS2: | |
| if (intp->chip_id >= 0x20) | |
| stv0900_write_reg(intp, CORRELABS, 0x79); | |
| else | |
| stv0900_write_reg(intp, CORRELABS, 0x68); | |
| stv0900_write_reg(intp, DMDCFGMD, 0x89); | |
| zigzag = TRUE; | |
| break; | |
| case STV0900_AUTO_SEARCH: | |
| default: | |
| if (intp->chip_id >= 0x20) { | |
| stv0900_write_reg(intp, CARFREQ, 0x3b); | |
| stv0900_write_reg(intp, CORRELABS, 0x79); | |
| } else { | |
| stv0900_write_reg(intp, CARFREQ, 0xef); | |
| stv0900_write_reg(intp, CORRELABS, 0x68); | |
| } | |
| stv0900_write_reg(intp, DMDCFGMD, 0xc9); | |
| zigzag = FALSE; | |
| break; | |
| } | |
| trial_cntr = 0; | |
| do { | |
| lock = stv0900_search_carr_sw_loop(intp, | |
| fqc_inc, | |
| sft_stp_tout, | |
| zigzag, | |
| max_steps, | |
| demod); | |
| no_signal = stv0900_check_signal_presence(intp, demod); | |
| trial_cntr++; | |
| if ((lock == TRUE) | |
| || (no_signal == TRUE) | |
| || (trial_cntr == 2)) { | |
| if (intp->chip_id >= 0x20) { | |
| stv0900_write_reg(intp, CARFREQ, 0x49); | |
| stv0900_write_reg(intp, CORRELABS, 0x9e); | |
| } else { | |
| stv0900_write_reg(intp, CARFREQ, 0xed); | |
| stv0900_write_reg(intp, CORRELABS, 0x88); | |
| } | |
| if ((stv0900_get_bits(intp, HEADER_MODE) == | |
| STV0900_DVBS2_FOUND) && | |
| (lock == TRUE)) { | |
| msleep(sft_stp_tout); | |
| s2fw = stv0900_get_bits(intp, FLYWHEEL_CPT); | |
| if (s2fw < 0xd) { | |
| msleep(sft_stp_tout); | |
| s2fw = stv0900_get_bits(intp, | |
| FLYWHEEL_CPT); | |
| } | |
| if (s2fw < 0xd) { | |
| lock = FALSE; | |
| if (trial_cntr < 2) { | |
| if (intp->chip_id >= 0x20) | |
| stv0900_write_reg(intp, | |
| CORRELABS, | |
| 0x79); | |
| else | |
| stv0900_write_reg(intp, | |
| CORRELABS, | |
| 0x68); | |
| stv0900_write_reg(intp, | |
| DMDCFGMD, | |
| 0x89); | |
| } | |
| } | |
| } | |
| } | |
| } while ((lock == FALSE) | |
| && (trial_cntr < 2) | |
| && (no_signal == FALSE)); | |
| return lock; | |
| } | |
| static u32 stv0900_get_symbol_rate(struct stv0900_internal *intp, | |
| u32 mclk, | |
| enum fe_stv0900_demod_num demod) | |
| { | |
| s32 rem1, rem2, intval1, intval2, srate; | |
| srate = (stv0900_get_bits(intp, SYMB_FREQ3) << 24) + | |
| (stv0900_get_bits(intp, SYMB_FREQ2) << 16) + | |
| (stv0900_get_bits(intp, SYMB_FREQ1) << 8) + | |
| (stv0900_get_bits(intp, SYMB_FREQ0)); | |
| dprintk("lock: srate=%d r0=0x%x r1=0x%x r2=0x%x r3=0x%x \n", | |
| srate, stv0900_get_bits(intp, SYMB_FREQ0), | |
| stv0900_get_bits(intp, SYMB_FREQ1), | |
| stv0900_get_bits(intp, SYMB_FREQ2), | |
| stv0900_get_bits(intp, SYMB_FREQ3)); | |
| intval1 = (mclk) >> 16; | |
| intval2 = (srate) >> 16; | |
| rem1 = (mclk) % 0x10000; | |
| rem2 = (srate) % 0x10000; | |
| srate = (intval1 * intval2) + | |
| ((intval1 * rem2) >> 16) + | |
| ((intval2 * rem1) >> 16); | |
| return srate; | |
| } | |
| static void stv0900_set_symbol_rate(struct stv0900_internal *intp, | |
| u32 mclk, u32 srate, | |
| enum fe_stv0900_demod_num demod) | |
| { | |
| u32 symb; | |
| dprintk("%s: Mclk %d, SR %d, Dmd %d\n", __func__, mclk, | |
| srate, demod); | |
| if (srate > 60000000) { | |
| symb = srate << 4; | |
| symb /= (mclk >> 12); | |
| } else if (srate > 6000000) { | |
| symb = srate << 6; | |
| symb /= (mclk >> 10); | |
| } else { | |
| symb = srate << 9; | |
| symb /= (mclk >> 7); | |
| } | |
| stv0900_write_reg(intp, SFRINIT1, (symb >> 8) & 0x7f); | |
| stv0900_write_reg(intp, SFRINIT1 + 1, (symb & 0xff)); | |
| } | |
| static void stv0900_set_max_symbol_rate(struct stv0900_internal *intp, | |
| u32 mclk, u32 srate, | |
| enum fe_stv0900_demod_num demod) | |
| { | |
| u32 symb; | |
| srate = 105 * (srate / 100); | |
| if (srate > 60000000) { | |
| symb = srate << 4; | |
| symb /= (mclk >> 12); | |
| } else if (srate > 6000000) { | |
| symb = srate << 6; | |
| symb /= (mclk >> 10); | |
| } else { | |
| symb = srate << 9; | |
| symb /= (mclk >> 7); | |
| } | |
| if (symb < 0x7fff) { | |
| stv0900_write_reg(intp, SFRUP1, (symb >> 8) & 0x7f); | |
| stv0900_write_reg(intp, SFRUP1 + 1, (symb & 0xff)); | |
| } else { | |
| stv0900_write_reg(intp, SFRUP1, 0x7f); | |
| stv0900_write_reg(intp, SFRUP1 + 1, 0xff); | |
| } | |
| } | |
| static void stv0900_set_min_symbol_rate(struct stv0900_internal *intp, | |
| u32 mclk, u32 srate, | |
| enum fe_stv0900_demod_num demod) | |
| { | |
| u32 symb; | |
| srate = 95 * (srate / 100); | |
| if (srate > 60000000) { | |
| symb = srate << 4; | |
| symb /= (mclk >> 12); | |
| } else if (srate > 6000000) { | |
| symb = srate << 6; | |
| symb /= (mclk >> 10); | |
| } else { | |
| symb = srate << 9; | |
| symb /= (mclk >> 7); | |
| } | |
| stv0900_write_reg(intp, SFRLOW1, (symb >> 8) & 0xff); | |
| stv0900_write_reg(intp, SFRLOW1 + 1, (symb & 0xff)); | |
| } | |
| static s32 stv0900_get_timing_offst(struct stv0900_internal *intp, | |
| u32 srate, | |
| enum fe_stv0900_demod_num demod) | |
| { | |
| s32 timingoffset; | |
| timingoffset = (stv0900_read_reg(intp, TMGREG2) << 16) + | |
| (stv0900_read_reg(intp, TMGREG2 + 1) << 8) + | |
| (stv0900_read_reg(intp, TMGREG2 + 2)); | |
| timingoffset = ge2comp(timingoffset, 24); | |
| if (timingoffset == 0) | |
| timingoffset = 1; | |
| timingoffset = ((s32)srate * 10) / ((s32)0x1000000 / timingoffset); | |
| timingoffset /= 320; | |
| return timingoffset; | |
| } | |
| static void stv0900_set_dvbs2_rolloff(struct stv0900_internal *intp, | |
| enum fe_stv0900_demod_num demod) | |
| { | |
| s32 rolloff; | |
| if (intp->chip_id == 0x10) { | |
| stv0900_write_bits(intp, MANUALSX_ROLLOFF, 1); | |
| rolloff = stv0900_read_reg(intp, MATSTR1) & 0x03; | |
| stv0900_write_bits(intp, ROLLOFF_CONTROL, rolloff); | |
| } else if (intp->chip_id <= 0x20) | |
| stv0900_write_bits(intp, MANUALSX_ROLLOFF, 0); | |
| else /* cut 3.0 */ | |
| stv0900_write_bits(intp, MANUALS2_ROLLOFF, 0); | |
| } | |
| static u32 stv0900_carrier_width(u32 srate, enum fe_stv0900_rolloff ro) | |
| { | |
| u32 rolloff; | |
| switch (ro) { | |
| case STV0900_20: | |
| rolloff = 20; | |
| break; | |
| case STV0900_25: | |
| rolloff = 25; | |
| break; | |
| case STV0900_35: | |
| default: | |
| rolloff = 35; | |
| break; | |
| } | |
| return srate + (srate * rolloff) / 100; | |
| } | |
| static int stv0900_check_timing_lock(struct stv0900_internal *intp, | |
| enum fe_stv0900_demod_num demod) | |
| { | |
| int timingLock = FALSE; | |
| s32 i, | |
| timingcpt = 0; | |
| u8 car_freq, | |
| tmg_th_high, | |
| tmg_th_low; | |
| car_freq = stv0900_read_reg(intp, CARFREQ); | |
| tmg_th_high = stv0900_read_reg(intp, TMGTHRISE); | |
| tmg_th_low = stv0900_read_reg(intp, TMGTHFALL); | |
| stv0900_write_reg(intp, TMGTHRISE, 0x20); | |
| stv0900_write_reg(intp, TMGTHFALL, 0x0); | |
| stv0900_write_bits(intp, CFR_AUTOSCAN, 0); | |
| stv0900_write_reg(intp, RTC, 0x80); | |
| stv0900_write_reg(intp, RTCS2, 0x40); | |
| stv0900_write_reg(intp, CARFREQ, 0x0); | |
| stv0900_write_reg(intp, CFRINIT1, 0x0); | |
| stv0900_write_reg(intp, CFRINIT0, 0x0); | |
| stv0900_write_reg(intp, AGC2REF, 0x65); | |
| stv0900_write_reg(intp, DMDISTATE, 0x18); | |
| msleep(7); | |
| for (i = 0; i < 10; i++) { | |
| if (stv0900_get_bits(intp, TMGLOCK_QUALITY) >= 2) | |
| timingcpt++; | |
| msleep(1); | |
| } | |
| if (timingcpt >= 3) | |
| timingLock = TRUE; | |
| stv0900_write_reg(intp, AGC2REF, 0x38); | |
| stv0900_write_reg(intp, RTC, 0x88); | |
| stv0900_write_reg(intp, RTCS2, 0x68); | |
| stv0900_write_reg(intp, CARFREQ, car_freq); | |
| stv0900_write_reg(intp, TMGTHRISE, tmg_th_high); | |
| stv0900_write_reg(intp, TMGTHFALL, tmg_th_low); | |
| return timingLock; | |
| } | |
| static int stv0900_get_demod_cold_lock(struct dvb_frontend *fe, | |
| s32 demod_timeout) | |
| { | |
| struct stv0900_state *state = fe->demodulator_priv; | |
| struct stv0900_internal *intp = state->internal; | |
| enum fe_stv0900_demod_num demod = state->demod; | |
| int lock = FALSE, | |
| d = demod; | |
| s32 srate, | |
| search_range, | |
| locktimeout, | |
| currier_step, | |
| nb_steps, | |
| current_step, | |
| direction, | |
| tuner_freq, | |
| timeout, | |
| freq; | |
| srate = intp->symbol_rate[d]; | |
| search_range = intp->srch_range[d]; | |
| if (srate >= 10000000) | |
| locktimeout = demod_timeout / 3; | |
| else | |
| locktimeout = demod_timeout / 2; | |
| lock = stv0900_get_demod_lock(intp, d, locktimeout); | |
| if (lock != FALSE) | |
| return lock; | |
| if (srate >= 10000000) { | |
| if (stv0900_check_timing_lock(intp, d) == TRUE) { | |
| stv0900_write_reg(intp, DMDISTATE, 0x1f); | |
| stv0900_write_reg(intp, DMDISTATE, 0x15); | |
| lock = stv0900_get_demod_lock(intp, d, demod_timeout); | |
| } else | |
| lock = FALSE; | |
| return lock; | |
| } | |
| if (intp->chip_id <= 0x20) { | |
| if (srate <= 1000000) | |
| currier_step = 500; | |
| else if (srate <= 4000000) | |
| currier_step = 1000; | |
| else if (srate <= 7000000) | |
| currier_step = 2000; | |
| else if (srate <= 10000000) | |
| currier_step = 3000; | |
| else | |
| currier_step = 5000; | |
| if (srate >= 2000000) { | |
| timeout = (demod_timeout / 3); | |
| if (timeout > 1000) | |
| timeout = 1000; | |
| } else | |
| timeout = (demod_timeout / 2); | |
| } else { | |
| /*cut 3.0 */ | |
| currier_step = srate / 4000; | |
| timeout = (demod_timeout * 3) / 4; | |
| } | |
| nb_steps = ((search_range / 1000) / currier_step); | |
| if ((nb_steps % 2) != 0) | |
| nb_steps += 1; | |
| if (nb_steps <= 0) | |
| nb_steps = 2; | |
| else if (nb_steps > 12) | |
| nb_steps = 12; | |
| current_step = 1; | |
| direction = 1; | |
| if (intp->chip_id <= 0x20) { | |
| tuner_freq = intp->freq[d]; | |
| intp->bw[d] = stv0900_carrier_width(intp->symbol_rate[d], | |
| intp->rolloff) + intp->symbol_rate[d]; | |
| } else | |
| tuner_freq = 0; | |
| while ((current_step <= nb_steps) && (lock == FALSE)) { | |
| if (direction > 0) | |
| tuner_freq += (current_step * currier_step); | |
| else | |
| tuner_freq -= (current_step * currier_step); | |
| if (intp->chip_id <= 0x20) { | |
| if (intp->tuner_type[d] == 3) | |
| stv0900_set_tuner_auto(intp, tuner_freq, | |
| intp->bw[d], demod); | |
| else | |
| stv0900_set_tuner(fe, tuner_freq, intp->bw[d]); | |
| stv0900_write_reg(intp, DMDISTATE, 0x1c); | |
| stv0900_write_reg(intp, CFRINIT1, 0); | |
| stv0900_write_reg(intp, CFRINIT0, 0); | |
| stv0900_write_reg(intp, DMDISTATE, 0x1f); | |
| stv0900_write_reg(intp, DMDISTATE, 0x15); | |
| } else { | |
| stv0900_write_reg(intp, DMDISTATE, 0x1c); | |
| freq = (tuner_freq * 65536) / (intp->mclk / 1000); | |
| stv0900_write_bits(intp, CFR_INIT1, MSB(freq)); | |
| stv0900_write_bits(intp, CFR_INIT0, LSB(freq)); | |
| stv0900_write_reg(intp, DMDISTATE, 0x1f); | |
| stv0900_write_reg(intp, DMDISTATE, 0x05); | |
| } | |
| lock = stv0900_get_demod_lock(intp, d, timeout); | |
| direction *= -1; | |
| current_step++; | |
| } | |
| return lock; | |
| } | |
| static void stv0900_get_lock_timeout(s32 *demod_timeout, s32 *fec_timeout, | |
| s32 srate, | |
| enum fe_stv0900_search_algo algo) | |
| { | |
| switch (algo) { | |
| case STV0900_BLIND_SEARCH: | |
| if (srate <= 1500000) { | |
| (*demod_timeout) = 1500; | |
| (*fec_timeout) = 400; | |
| } else if (srate <= 5000000) { | |
| (*demod_timeout) = 1000; | |
| (*fec_timeout) = 300; | |
| } else { | |
| (*demod_timeout) = 700; | |
| (*fec_timeout) = 100; | |
| } | |
| break; | |
| case STV0900_COLD_START: | |
| case STV0900_WARM_START: | |
| default: | |
| if (srate <= 1000000) { | |
| (*demod_timeout) = 3000; | |
| (*fec_timeout) = 1700; | |
| } else if (srate <= 2000000) { | |
| (*demod_timeout) = 2500; | |
| (*fec_timeout) = 1100; | |
| } else if (srate <= 5000000) { | |
| (*demod_timeout) = 1000; | |
| (*fec_timeout) = 550; | |
| } else if (srate <= 10000000) { | |
| (*demod_timeout) = 700; | |
| (*fec_timeout) = 250; | |
| } else if (srate <= 20000000) { | |
| (*demod_timeout) = 400; | |
| (*fec_timeout) = 130; | |
| } else { | |
| (*demod_timeout) = 300; | |
| (*fec_timeout) = 100; | |
| } | |
| break; | |
| } | |
| if (algo == STV0900_WARM_START) | |
| (*demod_timeout) /= 2; | |
| } | |
| static void stv0900_set_viterbi_tracq(struct stv0900_internal *intp, | |
| enum fe_stv0900_demod_num demod) | |
| { | |
| s32 vth_reg = VTH12; | |
| dprintk("%s\n", __func__); | |
| stv0900_write_reg(intp, vth_reg++, 0xd0); | |
| stv0900_write_reg(intp, vth_reg++, 0x7d); | |
| stv0900_write_reg(intp, vth_reg++, 0x53); | |
| stv0900_write_reg(intp, vth_reg++, 0x2f); | |
| stv0900_write_reg(intp, vth_reg++, 0x24); | |
| stv0900_write_reg(intp, vth_reg++, 0x1f); | |
| } | |
| static void stv0900_set_viterbi_standard(struct stv0900_internal *intp, | |
| enum fe_stv0900_search_standard standard, | |
| enum fe_stv0900_fec fec, | |
| enum fe_stv0900_demod_num demod) | |
| { | |
| dprintk("%s: ViterbiStandard = ", __func__); | |
| switch (standard) { | |
| case STV0900_AUTO_SEARCH: | |
| dprintk("Auto\n"); | |
| stv0900_write_reg(intp, FECM, 0x10); | |
| stv0900_write_reg(intp, PRVIT, 0x3f); | |
| break; | |
| case STV0900_SEARCH_DVBS1: | |
| dprintk("DVBS1\n"); | |
| stv0900_write_reg(intp, FECM, 0x00); | |
| switch (fec) { | |
| case STV0900_FEC_UNKNOWN: | |
| default: | |
| stv0900_write_reg(intp, PRVIT, 0x2f); | |
| break; | |
| case STV0900_FEC_1_2: | |
| stv0900_write_reg(intp, PRVIT, 0x01); | |
| break; | |
| case STV0900_FEC_2_3: | |
| stv0900_write_reg(intp, PRVIT, 0x02); | |
| break; | |
| case STV0900_FEC_3_4: | |
| stv0900_write_reg(intp, PRVIT, 0x04); | |
| break; | |
| case STV0900_FEC_5_6: | |
| stv0900_write_reg(intp, PRVIT, 0x08); | |
| break; | |
| case STV0900_FEC_7_8: | |
| stv0900_write_reg(intp, PRVIT, 0x20); | |
| break; | |
| } | |
| break; | |
| case STV0900_SEARCH_DSS: | |
| dprintk("DSS\n"); | |
| stv0900_write_reg(intp, FECM, 0x80); | |
| switch (fec) { | |
| case STV0900_FEC_UNKNOWN: | |
| default: | |
| stv0900_write_reg(intp, PRVIT, 0x13); | |
| break; | |
| case STV0900_FEC_1_2: | |
| stv0900_write_reg(intp, PRVIT, 0x01); | |
| break; | |
| case STV0900_FEC_2_3: | |
| stv0900_write_reg(intp, PRVIT, 0x02); | |
| break; | |
| case STV0900_FEC_6_7: | |
| stv0900_write_reg(intp, PRVIT, 0x10); | |
| break; | |
| } | |
| break; | |
| default: | |
| break; | |
| } | |
| } | |
| static enum fe_stv0900_fec stv0900_get_vit_fec(struct stv0900_internal *intp, | |
| enum fe_stv0900_demod_num demod) | |
| { | |
| enum fe_stv0900_fec prate; | |
| s32 rate_fld = stv0900_get_bits(intp, VIT_CURPUN); | |
| switch (rate_fld) { | |
| case 13: | |
| prate = STV0900_FEC_1_2; | |
| break; | |
| case 18: | |
| prate = STV0900_FEC_2_3; | |
| break; | |
| case 21: | |
| prate = STV0900_FEC_3_4; | |
| break; | |
| case 24: | |
| prate = STV0900_FEC_5_6; | |
| break; | |
| case 25: | |
| prate = STV0900_FEC_6_7; | |
| break; | |
| case 26: | |
| prate = STV0900_FEC_7_8; | |
| break; | |
| default: | |
| prate = STV0900_FEC_UNKNOWN; | |
| break; | |
| } | |
| return prate; | |
| } | |
| static void stv0900_set_dvbs1_track_car_loop(struct stv0900_internal *intp, | |
| enum fe_stv0900_demod_num demod, | |
| u32 srate) | |
| { | |
| if (intp->chip_id >= 0x30) { | |
| if (srate >= 15000000) { | |
| stv0900_write_reg(intp, ACLC, 0x2b); | |
| stv0900_write_reg(intp, BCLC, 0x1a); | |
| } else if ((srate >= 7000000) && (15000000 > srate)) { | |
| stv0900_write_reg(intp, ACLC, 0x0c); | |
| stv0900_write_reg(intp, BCLC, 0x1b); | |
| } else if (srate < 7000000) { | |
| stv0900_write_reg(intp, ACLC, 0x2c); | |
| stv0900_write_reg(intp, BCLC, 0x1c); | |
| } | |
| } else { /*cut 2.0 and 1.x*/ | |
| stv0900_write_reg(intp, ACLC, 0x1a); | |
| stv0900_write_reg(intp, BCLC, 0x09); | |
| } | |
| } | |
| static void stv0900_track_optimization(struct dvb_frontend *fe) | |
| { | |
| struct stv0900_state *state = fe->demodulator_priv; | |
| struct stv0900_internal *intp = state->internal; | |
| enum fe_stv0900_demod_num demod = state->demod; | |
| s32 srate, | |
| pilots, | |
| aclc, | |
| freq1, | |
| freq0, | |
| i = 0, | |
| timed, | |
| timef, | |
| blind_tun_sw = 0, | |
| modulation; | |
| enum fe_stv0900_modcode foundModcod; | |
| dprintk("%s\n", __func__); | |
| srate = stv0900_get_symbol_rate(intp, intp->mclk, demod); | |
| srate += stv0900_get_timing_offst(intp, srate, demod); | |
| switch (intp->result[demod].standard) { | |
| case STV0900_DVBS1_STANDARD: | |
| case STV0900_DSS_STANDARD: | |
| dprintk("%s: found DVB-S or DSS\n", __func__); | |
| if (intp->srch_standard[demod] == STV0900_AUTO_SEARCH) { | |
| stv0900_write_bits(intp, DVBS1_ENABLE, 1); | |
| stv0900_write_bits(intp, DVBS2_ENABLE, 0); | |
| } | |
| stv0900_write_bits(intp, ROLLOFF_CONTROL, intp->rolloff); | |
| stv0900_write_bits(intp, MANUALSX_ROLLOFF, 1); | |
| if (intp->chip_id < 0x30) { | |
| stv0900_write_reg(intp, ERRCTRL1, 0x75); | |
| break; | |
| } | |
| if (stv0900_get_vit_fec(intp, demod) == STV0900_FEC_1_2) { | |
| stv0900_write_reg(intp, GAUSSR0, 0x98); | |
| stv0900_write_reg(intp, CCIR0, 0x18); | |
| } else { | |
| stv0900_write_reg(intp, GAUSSR0, 0x18); | |
| stv0900_write_reg(intp, CCIR0, 0x18); | |
| } | |
| stv0900_write_reg(intp, ERRCTRL1, 0x75); | |
| break; | |
| case STV0900_DVBS2_STANDARD: | |
| dprintk("%s: found DVB-S2\n", __func__); | |
| stv0900_write_bits(intp, DVBS1_ENABLE, 0); | |
| stv0900_write_bits(intp, DVBS2_ENABLE, 1); | |
| stv0900_write_reg(intp, ACLC, 0); | |
| stv0900_write_reg(intp, BCLC, 0); | |
| if (intp->result[demod].frame_len == STV0900_LONG_FRAME) { | |
| foundModcod = stv0900_get_bits(intp, DEMOD_MODCOD); | |
| pilots = stv0900_get_bits(intp, DEMOD_TYPE) & 0x01; | |
| aclc = stv0900_get_optim_carr_loop(srate, | |
| foundModcod, | |
| pilots, | |
| intp->chip_id); | |
| if (foundModcod <= STV0900_QPSK_910) | |
| stv0900_write_reg(intp, ACLC2S2Q, aclc); | |
| else if (foundModcod <= STV0900_8PSK_910) { | |
| stv0900_write_reg(intp, ACLC2S2Q, 0x2a); | |
| stv0900_write_reg(intp, ACLC2S28, aclc); | |
| } | |
| if ((intp->demod_mode == STV0900_SINGLE) && | |
| (foundModcod > STV0900_8PSK_910)) { | |
| if (foundModcod <= STV0900_16APSK_910) { | |
| stv0900_write_reg(intp, ACLC2S2Q, 0x2a); | |
| stv0900_write_reg(intp, ACLC2S216A, | |
| aclc); | |
| } else if (foundModcod <= STV0900_32APSK_910) { | |
| stv0900_write_reg(intp, ACLC2S2Q, 0x2a); | |
| stv0900_write_reg(intp, ACLC2S232A, | |
| aclc); | |
| } | |
| } | |
| } else { | |
| modulation = intp->result[demod].modulation; | |
| aclc = stv0900_get_optim_short_carr_loop(srate, | |
| modulation, intp->chip_id); | |
| if (modulation == STV0900_QPSK) | |
| stv0900_write_reg(intp, ACLC2S2Q, aclc); | |
| else if (modulation == STV0900_8PSK) { | |
| stv0900_write_reg(intp, ACLC2S2Q, 0x2a); | |
| stv0900_write_reg(intp, ACLC2S28, aclc); | |
| } else if (modulation == STV0900_16APSK) { | |
| stv0900_write_reg(intp, ACLC2S2Q, 0x2a); | |
| stv0900_write_reg(intp, ACLC2S216A, aclc); | |
| } else if (modulation == STV0900_32APSK) { | |
| stv0900_write_reg(intp, ACLC2S2Q, 0x2a); | |
| stv0900_write_reg(intp, ACLC2S232A, aclc); | |
| } | |
| } | |
| if (intp->chip_id <= 0x11) { | |
| if (intp->demod_mode != STV0900_SINGLE) | |
| stv0900_activate_s2_modcod(intp, demod); | |
| } | |
| stv0900_write_reg(intp, ERRCTRL1, 0x67); | |
| break; | |
| case STV0900_UNKNOWN_STANDARD: | |
| default: | |
| dprintk("%s: found unknown standard\n", __func__); | |
| stv0900_write_bits(intp, DVBS1_ENABLE, 1); | |
| stv0900_write_bits(intp, DVBS2_ENABLE, 1); | |
| break; | |
| } | |
| freq1 = stv0900_read_reg(intp, CFR2); | |
| freq0 = stv0900_read_reg(intp, CFR1); | |
| if (intp->srch_algo[demod] == STV0900_BLIND_SEARCH) { | |
| stv0900_write_reg(intp, SFRSTEP, 0x00); | |
| stv0900_write_bits(intp, SCAN_ENABLE, 0); | |
| stv0900_write_bits(intp, CFR_AUTOSCAN, 0); | |
| stv0900_write_reg(intp, TMGCFG2, 0xc1); | |
| stv0900_set_symbol_rate(intp, intp->mclk, srate, demod); | |
| blind_tun_sw = 1; | |
| if (intp->result[demod].standard != STV0900_DVBS2_STANDARD) | |
| stv0900_set_dvbs1_track_car_loop(intp, demod, srate); | |
| } | |
| if (intp->chip_id >= 0x20) { | |
| if ((intp->srch_standard[demod] == STV0900_SEARCH_DVBS1) || | |
| (intp->srch_standard[demod] == | |
| STV0900_SEARCH_DSS) || | |
| (intp->srch_standard[demod] == | |
| STV0900_AUTO_SEARCH)) { | |
| stv0900_write_reg(intp, VAVSRVIT, 0x0a); | |
| stv0900_write_reg(intp, VITSCALE, 0x0); | |
| } | |
| } | |
| if (intp->chip_id < 0x20) | |
| stv0900_write_reg(intp, CARHDR, 0x08); | |
| if (intp->chip_id == 0x10) | |
| stv0900_write_reg(intp, CORRELEXP, 0x0a); | |
| stv0900_write_reg(intp, AGC2REF, 0x38); | |
| if ((intp->chip_id >= 0x20) || | |
| (blind_tun_sw == 1) || | |
| (intp->symbol_rate[demod] < 10000000)) { | |
| stv0900_write_reg(intp, CFRINIT1, freq1); | |
| stv0900_write_reg(intp, CFRINIT0, freq0); | |
| intp->bw[demod] = stv0900_carrier_width(srate, | |
| intp->rolloff) + 10000000; | |
| if ((intp->chip_id >= 0x20) || (blind_tun_sw == 1)) { | |
| if (intp->srch_algo[demod] != STV0900_WARM_START) { | |
| if (intp->tuner_type[demod] == 3) | |
| stv0900_set_tuner_auto(intp, | |
| intp->freq[demod], | |
| intp->bw[demod], | |
| demod); | |
| else | |
| stv0900_set_bandwidth(fe, | |
| intp->bw[demod]); | |
| } | |
| } | |
| if ((intp->srch_algo[demod] == STV0900_BLIND_SEARCH) || | |
| (intp->symbol_rate[demod] < 10000000)) | |
| msleep(50); | |
| else | |
| msleep(5); | |
| stv0900_get_lock_timeout(&timed, &timef, srate, | |
| STV0900_WARM_START); | |
| if (stv0900_get_demod_lock(intp, demod, timed / 2) == FALSE) { | |
| stv0900_write_reg(intp, DMDISTATE, 0x1f); | |
| stv0900_write_reg(intp, CFRINIT1, freq1); | |
| stv0900_write_reg(intp, CFRINIT0, freq0); | |
| stv0900_write_reg(intp, DMDISTATE, 0x18); | |
| i = 0; | |
| while ((stv0900_get_demod_lock(intp, | |
| demod, | |
| timed / 2) == FALSE) && | |
| (i <= 2)) { | |
| stv0900_write_reg(intp, DMDISTATE, 0x1f); | |
| stv0900_write_reg(intp, CFRINIT1, freq1); | |
| stv0900_write_reg(intp, CFRINIT0, freq0); | |
| stv0900_write_reg(intp, DMDISTATE, 0x18); | |
| i++; | |
| } | |
| } | |
| } | |
| if (intp->chip_id >= 0x20) | |
| stv0900_write_reg(intp, CARFREQ, 0x49); | |
| if ((intp->result[demod].standard == STV0900_DVBS1_STANDARD) || | |
| (intp->result[demod].standard == STV0900_DSS_STANDARD)) | |
| stv0900_set_viterbi_tracq(intp, demod); | |
| } | |
| static int stv0900_get_fec_lock(struct stv0900_internal *intp, | |
| enum fe_stv0900_demod_num demod, s32 time_out) | |
| { | |
| s32 timer = 0, lock = 0; | |
| enum fe_stv0900_search_state dmd_state; | |
| dprintk("%s\n", __func__); | |
| dmd_state = stv0900_get_bits(intp, HEADER_MODE); | |
| while ((timer < time_out) && (lock == 0)) { | |
| switch (dmd_state) { | |
| case STV0900_SEARCH: | |
| case STV0900_PLH_DETECTED: | |
| default: | |
| lock = 0; | |
| break; | |
| case STV0900_DVBS2_FOUND: | |
| lock = stv0900_get_bits(intp, PKTDELIN_LOCK); | |
| break; | |
| case STV0900_DVBS_FOUND: | |
| lock = stv0900_get_bits(intp, LOCKEDVIT); | |
| break; | |
| } | |
| if (lock == 0) { | |
| msleep(10); | |
| timer += 10; | |
| } | |
| } | |
| if (lock) | |
| dprintk("%s: DEMOD FEC LOCK OK\n", __func__); | |
| else | |
| dprintk("%s: DEMOD FEC LOCK FAIL\n", __func__); | |
| return lock; | |
| } | |
| static int stv0900_wait_for_lock(struct stv0900_internal *intp, | |
| enum fe_stv0900_demod_num demod, | |
| s32 dmd_timeout, s32 fec_timeout) | |
| { | |
| s32 timer = 0, lock = 0; | |
| dprintk("%s\n", __func__); | |
| lock = stv0900_get_demod_lock(intp, demod, dmd_timeout); | |
| if (lock) | |
| lock = stv0900_get_fec_lock(intp, demod, fec_timeout); | |
| if (lock) { | |
| lock = 0; | |
| dprintk("%s: Timer = %d, time_out = %d\n", | |
| __func__, timer, fec_timeout); | |
| while ((timer < fec_timeout) && (lock == 0)) { | |
| lock = stv0900_get_bits(intp, TSFIFO_LINEOK); | |
| msleep(1); | |
| timer++; | |
| } | |
| } | |
| if (lock) | |
| dprintk("%s: DEMOD LOCK OK\n", __func__); | |
| else | |
| dprintk("%s: DEMOD LOCK FAIL\n", __func__); | |
| if (lock) | |
| return TRUE; | |
| else | |
| return FALSE; | |
| } | |
| enum fe_stv0900_tracking_standard stv0900_get_standard(struct dvb_frontend *fe, | |
| enum fe_stv0900_demod_num demod) | |
| { | |
| struct stv0900_state *state = fe->demodulator_priv; | |
| struct stv0900_internal *intp = state->internal; | |
| enum fe_stv0900_tracking_standard fnd_standard; | |
| int hdr_mode = stv0900_get_bits(intp, HEADER_MODE); | |
| switch (hdr_mode) { | |
| case 2: | |
| fnd_standard = STV0900_DVBS2_STANDARD; | |
| break; | |
| case 3: | |
| if (stv0900_get_bits(intp, DSS_DVB) == 1) | |
| fnd_standard = STV0900_DSS_STANDARD; | |
| else | |
| fnd_standard = STV0900_DVBS1_STANDARD; | |
| break; | |
| default: | |
| fnd_standard = STV0900_UNKNOWN_STANDARD; | |
| } | |
| dprintk("%s: standard %d\n", __func__, fnd_standard); | |
| return fnd_standard; | |
| } | |
| static s32 stv0900_get_carr_freq(struct stv0900_internal *intp, u32 mclk, | |
| enum fe_stv0900_demod_num demod) | |
| { | |
| s32 derot, | |
| rem1, | |
| rem2, | |
| intval1, | |
| intval2; | |
| derot = (stv0900_get_bits(intp, CAR_FREQ2) << 16) + | |
| (stv0900_get_bits(intp, CAR_FREQ1) << 8) + | |
| (stv0900_get_bits(intp, CAR_FREQ0)); | |
| derot = ge2comp(derot, 24); | |
| intval1 = mclk >> 12; | |
| intval2 = derot >> 12; | |
| rem1 = mclk % 0x1000; | |
| rem2 = derot % 0x1000; | |
| derot = (intval1 * intval2) + | |
| ((intval1 * rem2) >> 12) + | |
| ((intval2 * rem1) >> 12); | |
| return derot; | |
| } | |
| static u32 stv0900_get_tuner_freq(struct dvb_frontend *fe) | |
| { | |
| struct dvb_frontend_ops *frontend_ops = NULL; | |
| struct dvb_tuner_ops *tuner_ops = NULL; | |
| u32 freq = 0; | |
| frontend_ops = &fe->ops; | |
| tuner_ops = &frontend_ops->tuner_ops; | |
| if (tuner_ops->get_frequency) { | |
| if ((tuner_ops->get_frequency(fe, &freq)) < 0) | |
| dprintk("%s: Invalid parameter\n", __func__); | |
| else | |
| dprintk("%s: Frequency=%d\n", __func__, freq); | |
| } | |
| return freq; | |
| } | |
| static enum | |
| fe_stv0900_signal_type stv0900_get_signal_params(struct dvb_frontend *fe) | |
| { | |
| struct stv0900_state *state = fe->demodulator_priv; | |
| struct stv0900_internal *intp = state->internal; | |
| enum fe_stv0900_demod_num demod = state->demod; | |
| enum fe_stv0900_signal_type range = STV0900_OUTOFRANGE; | |
| struct stv0900_signal_info *result = &intp->result[demod]; | |
| s32 offsetFreq, | |
| srate_offset; | |
| int i = 0, | |
| d = demod; | |
| u8 timing; | |
| msleep(5); | |
| if (intp->srch_algo[d] == STV0900_BLIND_SEARCH) { | |
| timing = stv0900_read_reg(intp, TMGREG2); | |
| i = 0; | |
| stv0900_write_reg(intp, SFRSTEP, 0x5c); | |
| while ((i <= 50) && (timing != 0) && (timing != 0xff)) { | |
| timing = stv0900_read_reg(intp, TMGREG2); | |
| msleep(5); | |
| i += 5; | |
| } | |
| } | |
| result->standard = stv0900_get_standard(fe, d); | |
| if (intp->tuner_type[demod] == 3) | |
| result->frequency = stv0900_get_freq_auto(intp, d); | |
| else | |
| result->frequency = stv0900_get_tuner_freq(fe); | |
| offsetFreq = stv0900_get_carr_freq(intp, intp->mclk, d) / 1000; | |
| result->frequency += offsetFreq; | |
| result->symbol_rate = stv0900_get_symbol_rate(intp, intp->mclk, d); | |
| srate_offset = stv0900_get_timing_offst(intp, result->symbol_rate, d); | |
| result->symbol_rate += srate_offset; | |
| result->fec = stv0900_get_vit_fec(intp, d); | |
| result->modcode = stv0900_get_bits(intp, DEMOD_MODCOD); | |
| result->pilot = stv0900_get_bits(intp, DEMOD_TYPE) & 0x01; | |
| result->frame_len = ((u32)stv0900_get_bits(intp, DEMOD_TYPE)) >> 1; | |
| result->rolloff = stv0900_get_bits(intp, ROLLOFF_STATUS); | |
| dprintk("%s: modcode=0x%x \n", __func__, result->modcode); | |
| switch (result->standard) { | |
| case STV0900_DVBS2_STANDARD: | |
| result->spectrum = stv0900_get_bits(intp, SPECINV_DEMOD); | |
| if (result->modcode <= STV0900_QPSK_910) | |
| result->modulation = STV0900_QPSK; | |
| else if (result->modcode <= STV0900_8PSK_910) | |
| result->modulation = STV0900_8PSK; | |
| else if (result->modcode <= STV0900_16APSK_910) | |
| result->modulation = STV0900_16APSK; | |
| else if (result->modcode <= STV0900_32APSK_910) | |
| result->modulation = STV0900_32APSK; | |
| else | |
| result->modulation = STV0900_UNKNOWN; | |
| break; | |
| case STV0900_DVBS1_STANDARD: | |
| case STV0900_DSS_STANDARD: | |
| result->spectrum = stv0900_get_bits(intp, IQINV); | |
| result->modulation = STV0900_QPSK; | |
| break; | |
| default: | |
| break; | |
| } | |
| if ((intp->srch_algo[d] == STV0900_BLIND_SEARCH) || | |
| (intp->symbol_rate[d] < 10000000)) { | |
| offsetFreq = result->frequency - intp->freq[d]; | |
| if (intp->tuner_type[demod] == 3) | |
| intp->freq[d] = stv0900_get_freq_auto(intp, d); | |
| else | |
| intp->freq[d] = stv0900_get_tuner_freq(fe); | |
| if (ABS(offsetFreq) <= ((intp->srch_range[d] / 2000) + 500)) | |
| range = STV0900_RANGEOK; | |
| else if (ABS(offsetFreq) <= | |
| (stv0900_carrier_width(result->symbol_rate, | |
| result->rolloff) / 2000)) | |
| range = STV0900_RANGEOK; | |
| } else if (ABS(offsetFreq) <= ((intp->srch_range[d] / 2000) + 500)) | |
| range = STV0900_RANGEOK; | |
| dprintk("%s: range %d\n", __func__, range); | |
| return range; | |
| } | |
| static enum | |
| fe_stv0900_signal_type stv0900_dvbs1_acq_workaround(struct dvb_frontend *fe) | |
| { | |
| struct stv0900_state *state = fe->demodulator_priv; | |
| struct stv0900_internal *intp = state->internal; | |
| enum fe_stv0900_demod_num demod = state->demod; | |
| enum fe_stv0900_signal_type signal_type = STV0900_NODATA; | |
| s32 srate, | |
| demod_timeout, | |
| fec_timeout, | |
| freq1, | |
| freq0; | |
| intp->result[demod].locked = FALSE; | |
| if (stv0900_get_bits(intp, HEADER_MODE) == STV0900_DVBS_FOUND) { | |
| srate = stv0900_get_symbol_rate(intp, intp->mclk, demod); | |
| srate += stv0900_get_timing_offst(intp, srate, demod); | |
| if (intp->srch_algo[demod] == STV0900_BLIND_SEARCH) | |
| stv0900_set_symbol_rate(intp, intp->mclk, srate, demod); | |
| stv0900_get_lock_timeout(&demod_timeout, &fec_timeout, | |
| srate, STV0900_WARM_START); | |
| freq1 = stv0900_read_reg(intp, CFR2); | |
| freq0 = stv0900_read_reg(intp, CFR1); | |
| stv0900_write_bits(intp, CFR_AUTOSCAN, 0); | |
| stv0900_write_bits(intp, SPECINV_CONTROL, | |
| STV0900_IQ_FORCE_SWAPPED); | |
| stv0900_write_reg(intp, DMDISTATE, 0x1c); | |
| stv0900_write_reg(intp, CFRINIT1, freq1); | |
| stv0900_write_reg(intp, CFRINIT0, freq0); | |
| stv0900_write_reg(intp, DMDISTATE, 0x18); | |
| if (stv0900_wait_for_lock(intp, demod, | |
| demod_timeout, fec_timeout) == TRUE) { | |
| intp->result[demod].locked = TRUE; | |
| signal_type = stv0900_get_signal_params(fe); | |
| stv0900_track_optimization(fe); | |
| } else { | |
| stv0900_write_bits(intp, SPECINV_CONTROL, | |
| STV0900_IQ_FORCE_NORMAL); | |
| stv0900_write_reg(intp, DMDISTATE, 0x1c); | |
| stv0900_write_reg(intp, CFRINIT1, freq1); | |
| stv0900_write_reg(intp, CFRINIT0, freq0); | |
| stv0900_write_reg(intp, DMDISTATE, 0x18); | |
| if (stv0900_wait_for_lock(intp, demod, | |
| demod_timeout, fec_timeout) == TRUE) { | |
| intp->result[demod].locked = TRUE; | |
| signal_type = stv0900_get_signal_params(fe); | |
| stv0900_track_optimization(fe); | |
| } | |
| } | |
| } else | |
| intp->result[demod].locked = FALSE; | |
| return signal_type; | |
| } | |
| static u16 stv0900_blind_check_agc2_min_level(struct stv0900_internal *intp, | |
| enum fe_stv0900_demod_num demod) | |
| { | |
| u32 minagc2level = 0xffff, | |
| agc2level, | |
| init_freq, freq_step; | |
| s32 i, j, nb_steps, direction; | |
| dprintk("%s\n", __func__); | |
| stv0900_write_reg(intp, AGC2REF, 0x38); | |
| stv0900_write_bits(intp, SCAN_ENABLE, 0); | |
| stv0900_write_bits(intp, CFR_AUTOSCAN, 0); | |
| stv0900_write_bits(intp, AUTO_GUP, 1); | |
| stv0900_write_bits(intp, AUTO_GLOW, 1); | |
| stv0900_write_reg(intp, DMDT0M, 0x0); | |
| stv0900_set_symbol_rate(intp, intp->mclk, 1000000, demod); | |
| nb_steps = -1 + (intp->srch_range[demod] / 1000000); | |
| nb_steps /= 2; | |
| nb_steps = (2 * nb_steps) + 1; | |
| if (nb_steps < 0) | |
| nb_steps = 1; | |
| direction = 1; | |
| freq_step = (1000000 << 8) / (intp->mclk >> 8); | |
| init_freq = 0; | |
| for (i = 0; i < nb_steps; i++) { | |
| if (direction > 0) | |
| init_freq = init_freq + (freq_step * i); | |
| else | |
| init_freq = init_freq - (freq_step * i); | |
| direction *= -1; | |
| stv0900_write_reg(intp, DMDISTATE, 0x5C); | |
| stv0900_write_reg(intp, CFRINIT1, (init_freq >> 8) & 0xff); | |
| stv0900_write_reg(intp, CFRINIT0, init_freq & 0xff); | |
| stv0900_write_reg(intp, DMDISTATE, 0x58); | |
| msleep(10); | |
| agc2level = 0; | |
| for (j = 0; j < 10; j++) | |
| agc2level += (stv0900_read_reg(intp, AGC2I1) << 8) | |
| | stv0900_read_reg(intp, AGC2I0); | |
| agc2level /= 10; | |
| if (agc2level < minagc2level) | |
| minagc2level = agc2level; | |
| } | |
| return (u16)minagc2level; | |
| } | |
| static u32 stv0900_search_srate_coarse(struct dvb_frontend *fe) | |
| { | |
| struct stv0900_state *state = fe->demodulator_priv; | |
| struct stv0900_internal *intp = state->internal; | |
| enum fe_stv0900_demod_num demod = state->demod; | |
| int timing_lck = FALSE; | |
| s32 i, timingcpt = 0, | |
| direction = 1, | |
| nb_steps, | |
| current_step = 0, | |
| tuner_freq; | |
| u32 agc2_th, | |
| coarse_srate = 0, | |
| agc2_integr = 0, | |
| currier_step = 1200; | |
| if (intp->chip_id >= 0x30) | |
| agc2_th = 0x2e00; | |
| else | |
| agc2_th = 0x1f00; | |
| stv0900_write_bits(intp, DEMOD_MODE, 0x1f); | |
| stv0900_write_reg(intp, TMGCFG, 0x12); | |
| stv0900_write_reg(intp, TMGTHRISE, 0xf0); | |
| stv0900_write_reg(intp, TMGTHFALL, 0xe0); | |
| stv0900_write_bits(intp, SCAN_ENABLE, 1); | |
| stv0900_write_bits(intp, CFR_AUTOSCAN, 1); | |
| stv0900_write_reg(intp, SFRUP1, 0x83); | |
| stv0900_write_reg(intp, SFRUP0, 0xc0); | |
| stv0900_write_reg(intp, SFRLOW1, 0x82); | |
| stv0900_write_reg(intp, SFRLOW0, 0xa0); | |
| stv0900_write_reg(intp, DMDT0M, 0x0); | |
| stv0900_write_reg(intp, AGC2REF, 0x50); | |
| if (intp->chip_id >= 0x30) { | |
| stv0900_write_reg(intp, CARFREQ, 0x99); | |
| stv0900_write_reg(intp, SFRSTEP, 0x98); | |
| } else if (intp->chip_id >= 0x20) { | |
| stv0900_write_reg(intp, CARFREQ, 0x6a); | |
| stv0900_write_reg(intp, SFRSTEP, 0x95); | |
| } else { | |
| stv0900_write_reg(intp, CARFREQ, 0xed); | |
| stv0900_write_reg(intp, SFRSTEP, 0x73); | |
| } | |
| if (intp->symbol_rate[demod] <= 2000000) | |
| currier_step = 1000; | |
| else if (intp->symbol_rate[demod] <= 5000000) | |
| currier_step = 2000; | |
| else if (intp->symbol_rate[demod] <= 12000000) | |
| currier_step = 3000; | |
| else | |
| currier_step = 5000; | |
| nb_steps = -1 + ((intp->srch_range[demod] / 1000) / currier_step); | |
| nb_steps /= 2; | |
| nb_steps = (2 * nb_steps) + 1; | |
| if (nb_steps < 0) | |
| nb_steps = 1; | |
| else if (nb_steps > 10) { | |
| nb_steps = 11; | |
| currier_step = (intp->srch_range[demod] / 1000) / 10; | |
| } | |
| current_step = 0; | |
| direction = 1; | |
| tuner_freq = intp->freq[demod]; | |
| while ((timing_lck == FALSE) && (current_step < nb_steps)) { | |
| stv0900_write_reg(intp, DMDISTATE, 0x5f); | |
| stv0900_write_bits(intp, DEMOD_MODE, 0); | |
| msleep(50); | |
| for (i = 0; i < 10; i++) { | |
| if (stv0900_get_bits(intp, TMGLOCK_QUALITY) >= 2) | |
| timingcpt++; | |
| agc2_integr += (stv0900_read_reg(intp, AGC2I1) << 8) | | |
| stv0900_read_reg(intp, AGC2I0); | |
| } | |
| agc2_integr /= 10; | |
| coarse_srate = stv0900_get_symbol_rate(intp, intp->mclk, demod); | |
| current_step++; | |
| direction *= -1; | |
| dprintk("lock: I2C_DEMOD_MODE_FIELD =0. Search started." | |
| " tuner freq=%d agc2=0x%x srate_coarse=%d tmg_cpt=%d\n", | |
| tuner_freq, agc2_integr, coarse_srate, timingcpt); | |
| if ((timingcpt >= 5) && | |
| (agc2_integr < agc2_th) && | |
| (coarse_srate < 55000000) && | |
| (coarse_srate > 850000)) | |
| timing_lck = TRUE; | |
| else if (current_step < nb_steps) { | |
| if (direction > 0) | |
| tuner_freq += (current_step * currier_step); | |
| else | |
| tuner_freq -= (current_step * currier_step); | |
| if (intp->tuner_type[demod] == 3) | |
| stv0900_set_tuner_auto(intp, tuner_freq, | |
| intp->bw[demod], demod); | |
| else | |
| stv0900_set_tuner(fe, tuner_freq, | |
| intp->bw[demod]); | |
| } | |
| } | |
| if (timing_lck == FALSE) | |
| coarse_srate = 0; | |
| else | |
| coarse_srate = stv0900_get_symbol_rate(intp, intp->mclk, demod); | |
| return coarse_srate; | |
| } | |
| static u32 stv0900_search_srate_fine(struct dvb_frontend *fe) | |
| { | |
| struct stv0900_state *state = fe->demodulator_priv; | |
| struct stv0900_internal *intp = state->internal; | |
| enum fe_stv0900_demod_num demod = state->demod; | |
| u32 coarse_srate, | |
| coarse_freq, | |
| symb, | |
| symbmax, | |
| symbmin, | |
| symbcomp; | |
| coarse_srate = stv0900_get_symbol_rate(intp, intp->mclk, demod); | |
| if (coarse_srate > 3000000) { | |
| symbmax = 13 * (coarse_srate / 10); | |
| symbmax = (symbmax / 1000) * 65536; | |
| symbmax /= (intp->mclk / 1000); | |
| symbmin = 10 * (coarse_srate / 13); | |
| symbmin = (symbmin / 1000)*65536; | |
| symbmin /= (intp->mclk / 1000); | |
| symb = (coarse_srate / 1000) * 65536; | |
| symb /= (intp->mclk / 1000); | |
| } else { | |
| symbmax = 13 * (coarse_srate / 10); | |
| symbmax = (symbmax / 100) * 65536; | |
| symbmax /= (intp->mclk / 100); | |
| symbmin = 10 * (coarse_srate / 14); | |
| symbmin = (symbmin / 100) * 65536; | |
| symbmin /= (intp->mclk / 100); | |
| symb = (coarse_srate / 100) * 65536; | |
| symb /= (intp->mclk / 100); | |
| } | |
| symbcomp = 13 * (coarse_srate / 10); | |
| coarse_freq = (stv0900_read_reg(intp, CFR2) << 8) | |
| | stv0900_read_reg(intp, CFR1); | |
| if (symbcomp < intp->symbol_rate[demod]) | |
| coarse_srate = 0; | |
| else { | |
| stv0900_write_reg(intp, DMDISTATE, 0x1f); | |
| stv0900_write_reg(intp, TMGCFG2, 0xc1); | |
| stv0900_write_reg(intp, TMGTHRISE, 0x20); | |
| stv0900_write_reg(intp, TMGTHFALL, 0x00); | |
| stv0900_write_reg(intp, TMGCFG, 0xd2); | |
| stv0900_write_bits(intp, CFR_AUTOSCAN, 0); | |
| stv0900_write_reg(intp, AGC2REF, 0x38); | |
| if (intp->chip_id >= 0x30) | |
| stv0900_write_reg(intp, CARFREQ, 0x79); | |
| else if (intp->chip_id >= 0x20) | |
| stv0900_write_reg(intp, CARFREQ, 0x49); | |
| else | |
| stv0900_write_reg(intp, CARFREQ, 0xed); | |
| stv0900_write_reg(intp, SFRUP1, (symbmax >> 8) & 0x7f); | |
| stv0900_write_reg(intp, SFRUP0, (symbmax & 0xff)); | |
| stv0900_write_reg(intp, SFRLOW1, (symbmin >> 8) & 0x7f); | |
| stv0900_write_reg(intp, SFRLOW0, (symbmin & 0xff)); | |
| stv0900_write_reg(intp, SFRINIT1, (symb >> 8) & 0xff); | |
| stv0900_write_reg(intp, SFRINIT0, (symb & 0xff)); | |
| stv0900_write_reg(intp, DMDT0M, 0x20); | |
| stv0900_write_reg(intp, CFRINIT1, (coarse_freq >> 8) & 0xff); | |
| stv0900_write_reg(intp, CFRINIT0, coarse_freq & 0xff); | |
| stv0900_write_reg(intp, DMDISTATE, 0x15); | |
| } | |
| return coarse_srate; | |
| } | |
| static int stv0900_blind_search_algo(struct dvb_frontend *fe) | |
| { | |
| struct stv0900_state *state = fe->demodulator_priv; | |
| struct stv0900_internal *intp = state->internal; | |
| enum fe_stv0900_demod_num demod = state->demod; | |
| u8 k_ref_tmg, | |
| k_ref_tmg_max, | |
| k_ref_tmg_min; | |
| u32 coarse_srate, | |
| agc2_th; | |
| int lock = FALSE, | |
| coarse_fail = FALSE; | |
| s32 demod_timeout = 500, | |
| fec_timeout = 50, | |
| fail_cpt, | |
| i, | |
| agc2_overflow; | |
| u16 agc2_int; | |
| u8 dstatus2; | |
| dprintk("%s\n", __func__); | |
| if (intp->chip_id < 0x20) { | |
| k_ref_tmg_max = 233; | |
| k_ref_tmg_min = 143; | |
| } else { | |
| k_ref_tmg_max = 110; | |
| k_ref_tmg_min = 10; | |
| } | |
| if (intp->chip_id <= 0x20) | |
| agc2_th = STV0900_BLIND_SEARCH_AGC2_TH; | |
| else | |
| agc2_th = STV0900_BLIND_SEARCH_AGC2_TH_CUT30; | |
| agc2_int = stv0900_blind_check_agc2_min_level(intp, demod); | |
| dprintk("%s agc2_int=%d agc2_th=%d \n", __func__, agc2_int, agc2_th); | |
| if (agc2_int > agc2_th) | |
| return FALSE; | |
| if (intp->chip_id == 0x10) | |
| stv0900_write_reg(intp, CORRELEXP, 0xaa); | |
| if (intp->chip_id < 0x20) | |
| stv0900_write_reg(intp, CARHDR, 0x55); | |
| else | |
| stv0900_write_reg(intp, CARHDR, 0x20); | |
| if (intp->chip_id <= 0x20) | |
| stv0900_write_reg(intp, CARCFG, 0xc4); | |
| else | |
| stv0900_write_reg(intp, CARCFG, 0x6); | |
| stv0900_write_reg(intp, RTCS2, 0x44); | |
| if (intp->chip_id >= 0x20) { | |
| stv0900_write_reg(intp, EQUALCFG, 0x41); | |
| stv0900_write_reg(intp, FFECFG, 0x41); | |
| stv0900_write_reg(intp, VITSCALE, 0x82); | |
| stv0900_write_reg(intp, VAVSRVIT, 0x0); | |
| } | |
| k_ref_tmg = k_ref_tmg_max; | |
| do { | |
| stv0900_write_reg(intp, KREFTMG, k_ref_tmg); | |
| if (stv0900_search_srate_coarse(fe) != 0) { | |
| coarse_srate = stv0900_search_srate_fine(fe); | |
| if (coarse_srate != 0) { | |
| stv0900_get_lock_timeout(&demod_timeout, | |
| &fec_timeout, | |
| coarse_srate, | |
| STV0900_BLIND_SEARCH); | |
| lock = stv0900_get_demod_lock(intp, | |
| demod, | |
| demod_timeout); | |
| } else | |
| lock = FALSE; | |
| } else { | |
| fail_cpt = 0; | |
| agc2_overflow = 0; | |
| for (i = 0; i < 10; i++) { | |
| agc2_int = (stv0900_read_reg(intp, AGC2I1) << 8) | |
| | stv0900_read_reg(intp, AGC2I0); | |
| if (agc2_int >= 0xff00) | |
| agc2_overflow++; | |
| dstatus2 = stv0900_read_reg(intp, DSTATUS2); | |
| if (((dstatus2 & 0x1) == 0x1) && | |
| ((dstatus2 >> 7) == 1)) | |
| fail_cpt++; | |
| } | |
| if ((fail_cpt > 7) || (agc2_overflow > 7)) | |
| coarse_fail = TRUE; | |
| lock = FALSE; | |
| } | |
| k_ref_tmg -= 30; | |
| } while ((k_ref_tmg >= k_ref_tmg_min) && | |
| (lock == FALSE) && | |
| (coarse_fail == FALSE)); | |
| return lock; | |
| } | |
| static void stv0900_set_viterbi_acq(struct stv0900_internal *intp, | |
| enum fe_stv0900_demod_num demod) | |
| { | |
| s32 vth_reg = VTH12; | |
| dprintk("%s\n", __func__); | |
| stv0900_write_reg(intp, vth_reg++, 0x96); | |
| stv0900_write_reg(intp, vth_reg++, 0x64); | |
| stv0900_write_reg(intp, vth_reg++, 0x36); | |
| stv0900_write_reg(intp, vth_reg++, 0x23); | |
| stv0900_write_reg(intp, vth_reg++, 0x1e); | |
| stv0900_write_reg(intp, vth_reg++, 0x19); | |
| } | |
| static void stv0900_set_search_standard(struct stv0900_internal *intp, | |
| enum fe_stv0900_demod_num demod) | |
| { | |
| dprintk("%s\n", __func__); | |
| switch (intp->srch_standard[demod]) { | |
| case STV0900_SEARCH_DVBS1: | |
| dprintk("Search Standard = DVBS1\n"); | |
| break; | |
| case STV0900_SEARCH_DSS: | |
| dprintk("Search Standard = DSS\n"); | |
| break; | |
| case STV0900_SEARCH_DVBS2: | |
| dprintk("Search Standard = DVBS2\n"); | |
| break; | |
| case STV0900_AUTO_SEARCH: | |
| default: | |
| dprintk("Search Standard = AUTO\n"); | |
| break; | |
| } | |
| switch (intp->srch_standard[demod]) { | |
| case STV0900_SEARCH_DVBS1: | |
| case STV0900_SEARCH_DSS: | |
| stv0900_write_bits(intp, DVBS1_ENABLE, 1); | |
| stv0900_write_bits(intp, DVBS2_ENABLE, 0); | |
| stv0900_write_bits(intp, STOP_CLKVIT, 0); | |
| stv0900_set_dvbs1_track_car_loop(intp, | |
| demod, | |
| intp->symbol_rate[demod]); | |
| stv0900_write_reg(intp, CAR2CFG, 0x22); | |
| stv0900_set_viterbi_acq(intp, demod); | |
| stv0900_set_viterbi_standard(intp, | |
| intp->srch_standard[demod], | |
| intp->fec[demod], demod); | |
| break; | |
| case STV0900_SEARCH_DVBS2: | |
| stv0900_write_bits(intp, DVBS1_ENABLE, 0); | |
| stv0900_write_bits(intp, DVBS2_ENABLE, 1); | |
| stv0900_write_bits(intp, STOP_CLKVIT, 1); | |
| stv0900_write_reg(intp, ACLC, 0x1a); | |
| stv0900_write_reg(intp, BCLC, 0x09); | |
| if (intp->chip_id <= 0x20) /*cut 1.x and 2.0*/ | |
| stv0900_write_reg(intp, CAR2CFG, 0x26); | |
| else | |
| stv0900_write_reg(intp, CAR2CFG, 0x66); | |
| if (intp->demod_mode != STV0900_SINGLE) { | |
| if (intp->chip_id <= 0x11) | |
| stv0900_stop_all_s2_modcod(intp, demod); | |
| else | |
| stv0900_activate_s2_modcod(intp, demod); | |
| } else | |
| stv0900_activate_s2_modcod_single(intp, demod); | |
| stv0900_set_viterbi_tracq(intp, demod); | |
| break; | |
| case STV0900_AUTO_SEARCH: | |
| default: | |
| stv0900_write_bits(intp, DVBS1_ENABLE, 1); | |
| stv0900_write_bits(intp, DVBS2_ENABLE, 1); | |
| stv0900_write_bits(intp, STOP_CLKVIT, 0); | |
| stv0900_write_reg(intp, ACLC, 0x1a); | |
| stv0900_write_reg(intp, BCLC, 0x09); | |
| stv0900_set_dvbs1_track_car_loop(intp, | |
| demod, | |
| intp->symbol_rate[demod]); | |
| if (intp->chip_id <= 0x20) /*cut 1.x and 2.0*/ | |
| stv0900_write_reg(intp, CAR2CFG, 0x26); | |
| else | |
| stv0900_write_reg(intp, CAR2CFG, 0x66); | |
| if (intp->demod_mode != STV0900_SINGLE) { | |
| if (intp->chip_id <= 0x11) | |
| stv0900_stop_all_s2_modcod(intp, demod); | |
| else | |
| stv0900_activate_s2_modcod(intp, demod); | |
| } else | |
| stv0900_activate_s2_modcod_single(intp, demod); | |
| stv0900_set_viterbi_tracq(intp, demod); | |
| stv0900_set_viterbi_standard(intp, | |
| intp->srch_standard[demod], | |
| intp->fec[demod], demod); | |
| break; | |
| } | |
| } | |
| enum fe_stv0900_signal_type stv0900_algo(struct dvb_frontend *fe) | |
| { | |
| struct stv0900_state *state = fe->demodulator_priv; | |
| struct stv0900_internal *intp = state->internal; | |
| enum fe_stv0900_demod_num demod = state->demod; | |
| s32 demod_timeout = 500, fec_timeout = 50; | |
| s32 aq_power, agc1_power, i; | |
| int lock = FALSE, low_sr = FALSE; | |
| enum fe_stv0900_signal_type signal_type = STV0900_NOCARRIER; | |
| enum fe_stv0900_search_algo algo; | |
| int no_signal = FALSE; | |
| dprintk("%s\n", __func__); | |
| algo = intp->srch_algo[demod]; | |
| stv0900_write_bits(intp, RST_HWARE, 1); | |
| stv0900_write_reg(intp, DMDISTATE, 0x5c); | |
| if (intp->chip_id >= 0x20) { | |
| if (intp->symbol_rate[demod] > 5000000) | |
| stv0900_write_reg(intp, CORRELABS, 0x9e); | |
| else | |
| stv0900_write_reg(intp, CORRELABS, 0x82); | |
| } else | |
| stv0900_write_reg(intp, CORRELABS, 0x88); | |
| stv0900_get_lock_timeout(&demod_timeout, &fec_timeout, | |
| intp->symbol_rate[demod], | |
| intp->srch_algo[demod]); | |
| if (intp->srch_algo[demod] == STV0900_BLIND_SEARCH) { | |
| intp->bw[demod] = 2 * 36000000; | |
| stv0900_write_reg(intp, TMGCFG2, 0xc0); | |
| stv0900_write_reg(intp, CORRELMANT, 0x70); | |
| stv0900_set_symbol_rate(intp, intp->mclk, 1000000, demod); | |
| } else { | |
| stv0900_write_reg(intp, DMDT0M, 0x20); | |
| stv0900_write_reg(intp, TMGCFG, 0xd2); | |
| if (intp->symbol_rate[demod] < 2000000) | |
| stv0900_write_reg(intp, CORRELMANT, 0x63); | |
| else | |
| stv0900_write_reg(intp, CORRELMANT, 0x70); | |
| stv0900_write_reg(intp, AGC2REF, 0x38); | |
| intp->bw[demod] = | |
| stv0900_carrier_width(intp->symbol_rate[demod], | |
| intp->rolloff); | |
| if (intp->chip_id >= 0x20) { | |
| stv0900_write_reg(intp, KREFTMG, 0x5a); | |
| if (intp->srch_algo[demod] == STV0900_COLD_START) { | |
| intp->bw[demod] += 10000000; | |
| intp->bw[demod] *= 15; | |
| intp->bw[demod] /= 10; | |
| } else if (intp->srch_algo[demod] == STV0900_WARM_START) | |
| intp->bw[demod] += 10000000; | |
| } else { | |
| stv0900_write_reg(intp, KREFTMG, 0xc1); | |
| intp->bw[demod] += 10000000; | |
| intp->bw[demod] *= 15; | |
| intp->bw[demod] /= 10; | |
| } | |
| stv0900_write_reg(intp, TMGCFG2, 0xc1); | |
| stv0900_set_symbol_rate(intp, intp->mclk, | |
| intp->symbol_rate[demod], demod); | |
| stv0900_set_max_symbol_rate(intp, intp->mclk, | |
| intp->symbol_rate[demod], demod); | |
| stv0900_set_min_symbol_rate(intp, intp->mclk, | |
| intp->symbol_rate[demod], demod); | |
| if (intp->symbol_rate[demod] >= 10000000) | |
| low_sr = FALSE; | |
| else | |
| low_sr = TRUE; | |
| } | |
| if (intp->tuner_type[demod] == 3) | |
| stv0900_set_tuner_auto(intp, intp->freq[demod], | |
| intp->bw[demod], demod); | |
| else | |
| stv0900_set_tuner(fe, intp->freq[demod], intp->bw[demod]); | |
| agc1_power = MAKEWORD(stv0900_get_bits(intp, AGCIQ_VALUE1), | |
| stv0900_get_bits(intp, AGCIQ_VALUE0)); | |
| aq_power = 0; | |
| if (agc1_power == 0) { | |
| for (i = 0; i < 5; i++) | |
| aq_power += (stv0900_get_bits(intp, POWER_I) + | |
| stv0900_get_bits(intp, POWER_Q)) / 2; | |
| aq_power /= 5; | |
| } | |
| if ((agc1_power == 0) && (aq_power < IQPOWER_THRESHOLD)) { | |
| intp->result[demod].locked = FALSE; | |
| signal_type = STV0900_NOAGC1; | |
| dprintk("%s: NO AGC1, POWERI, POWERQ\n", __func__); | |
| } else { | |
| stv0900_write_bits(intp, SPECINV_CONTROL, | |
| intp->srch_iq_inv[demod]); | |
| if (intp->chip_id <= 0x20) /*cut 2.0*/ | |
| stv0900_write_bits(intp, MANUALSX_ROLLOFF, 1); | |
| else /*cut 3.0*/ | |
| stv0900_write_bits(intp, MANUALS2_ROLLOFF, 1); | |
| stv0900_set_search_standard(intp, demod); | |
| if (intp->srch_algo[demod] != STV0900_BLIND_SEARCH) | |
| stv0900_start_search(intp, demod); | |
| } | |
| if (signal_type == STV0900_NOAGC1) | |
| return signal_type; | |
| if (intp->chip_id == 0x12) { | |
| stv0900_write_bits(intp, RST_HWARE, 0); | |
| msleep(3); | |
| stv0900_write_bits(intp, RST_HWARE, 1); | |
| stv0900_write_bits(intp, RST_HWARE, 0); | |
| } | |
| if (algo == STV0900_BLIND_SEARCH) | |
| lock = stv0900_blind_search_algo(fe); | |
| else if (algo == STV0900_COLD_START) | |
| lock = stv0900_get_demod_cold_lock(fe, demod_timeout); | |
| else if (algo == STV0900_WARM_START) | |
| lock = stv0900_get_demod_lock(intp, demod, demod_timeout); | |
| if ((lock == FALSE) && (algo == STV0900_COLD_START)) { | |
| if (low_sr == FALSE) { | |
| if (stv0900_check_timing_lock(intp, demod) == TRUE) | |
| lock = stv0900_sw_algo(intp, demod); | |
| } | |
| } | |
| if (lock == TRUE) | |
| signal_type = stv0900_get_signal_params(fe); | |
| if ((lock == TRUE) && (signal_type == STV0900_RANGEOK)) { | |
| stv0900_track_optimization(fe); | |
| if (intp->chip_id <= 0x11) { | |
| if ((stv0900_get_standard(fe, 0) == | |
| STV0900_DVBS1_STANDARD) && | |
| (stv0900_get_standard(fe, 1) == | |
| STV0900_DVBS1_STANDARD)) { | |
| msleep(20); | |
| stv0900_write_bits(intp, RST_HWARE, 0); | |
| } else { | |
| stv0900_write_bits(intp, RST_HWARE, 0); | |
| msleep(3); | |
| stv0900_write_bits(intp, RST_HWARE, 1); | |
| stv0900_write_bits(intp, RST_HWARE, 0); | |
| } | |
| } else if (intp->chip_id >= 0x20) { | |
| stv0900_write_bits(intp, RST_HWARE, 0); | |
| msleep(3); | |
| stv0900_write_bits(intp, RST_HWARE, 1); | |
| stv0900_write_bits(intp, RST_HWARE, 0); | |
| } | |
| if (stv0900_wait_for_lock(intp, demod, | |
| fec_timeout, fec_timeout) == TRUE) { | |
| lock = TRUE; | |
| intp->result[demod].locked = TRUE; | |
| if (intp->result[demod].standard == | |
| STV0900_DVBS2_STANDARD) { | |
| stv0900_set_dvbs2_rolloff(intp, demod); | |
| stv0900_write_bits(intp, RESET_UPKO_COUNT, 1); | |
| stv0900_write_bits(intp, RESET_UPKO_COUNT, 0); | |
| stv0900_write_reg(intp, ERRCTRL1, 0x67); | |
| } else { | |
| stv0900_write_reg(intp, ERRCTRL1, 0x75); | |
| } | |
| stv0900_write_reg(intp, FBERCPT4, 0); | |
| stv0900_write_reg(intp, ERRCTRL2, 0xc1); | |
| } else { | |
| lock = FALSE; | |
| signal_type = STV0900_NODATA; | |
| no_signal = stv0900_check_signal_presence(intp, demod); | |
| intp->result[demod].locked = FALSE; | |
| } | |
| } | |
| if ((signal_type != STV0900_NODATA) || (no_signal != FALSE)) | |
| return signal_type; | |
| if (intp->chip_id > 0x11) { | |
| intp->result[demod].locked = FALSE; | |
| return signal_type; | |
| } | |
| if ((stv0900_get_bits(intp, HEADER_MODE) == STV0900_DVBS_FOUND) && | |
| (intp->srch_iq_inv[demod] <= STV0900_IQ_AUTO_NORMAL_FIRST)) | |
| signal_type = stv0900_dvbs1_acq_workaround(fe); | |
| return signal_type; | |
| } | |