diff -r fbcc9fa65f56 linux/drivers/media/dvb/frontends/stb0899_algo.c --- a/linux/drivers/media/dvb/frontends/stb0899_algo.c Wed May 28 12:08:48 2008 +0400 +++ b/linux/drivers/media/dvb/frontends/stb0899_algo.c Sun Jun 15 11:37:56 2008 +0200 @@ -48,6 +48,49 @@ static u32 stb0899_calc_srate(u32 master tmp >>= 24; return tmp; +} + +s32 stb0899_get_frequency_offset(struct stb0899_state *state) { + s32 offset = 0; + s16 w; + u8 cfr[2]; + + struct stb0899_internal *internal = &state->internal; + switch (state->delsys) { + case DVBFE_DELSYS_DVBS: + stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency */ + /* don't why it is 3/2 here */ + w = MAKEWORD16(cfr[0], cfr[1]); + offset = w * 3/2; + break; + case DVBFE_DELSYS_DVBS2: + offset = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ); + if (offset & 0x20000000) { + /* sign extension */ + offset |= 0xc0000000; + } + /* + * what is the range of offsetfreq here: assume +- 20MHz as sane range + * 1MHz -> offsetfreq = 1000kHz * (2^30/1000) / 99 = 10 845 877 + * offset/kHz = offsetfreq * mclk / 1e6 / 2^30 * 1e3 + * = (((offsetfreq / 1024) * 1000) * (mclk/1e6)) / 2^20 + */ +#if 0 + /* 64 Bit arithmetic */ + offset = (s32)((s64)offset * + ((s64)internal->master_clk / (s64)1000000) / + (s64)((1 << 30) / (s64)1000)); +#else + /* 32 Bit arithmetic */ + offset = ((((offset / 1024) * 1000) / (1<<7)) * (s32)(internal->master_clk/1000000)) / (s32)(1<<13); +#endif + break; + case DVBFE_DELSYS_DSS: + default: + /* TODO: */ + break; + } + return offset; } /* @@ -132,6 +175,8 @@ long stb0899_carr_width(struct stb0899_s return (internal->srate + (internal->srate * internal->rolloff) / 100); } + +#if 0 /* * stb0899_first_subrange * Compute the first subrange of the search @@ -161,6 +206,7 @@ static void stb0899_first_subrange(struc internal->tuner_offst = 0L; internal->sub_dir = 1; } +#endif /* * stb0899_check_tmg @@ -212,7 +258,7 @@ static enum stb0899_status stb0899_searc internal->status = NOTIMING; /* timing loop computation & symbol rate optimisation */ - derot_limit = (internal->sub_range / 2L) / internal->mclk; + derot_limit = 0;//(internal->sub_range / 2L) / internal->mclk; derot_step = (params->srate / 2L) / internal->mclk; while ((stb0899_check_tmg(state) != TIMINGOK) && next_loop) { @@ -267,6 +313,7 @@ static enum stb0899_status stb0899_check return internal->status; } +#if 0 /* * stb0899_search_carrier * Search for a QPSK carrier with the derotator @@ -322,6 +369,7 @@ static enum stb0899_status stb0899_searc return internal->status; } +#endif /* * stb0899_check_data @@ -390,7 +438,7 @@ static enum stb0899_status stb0899_searc struct stb0899_params *params = &state->params; derot_step = (params->srate / 4L) / internal->mclk; - derot_limit = (internal->sub_range / 2L) / internal->mclk; + derot_limit = 0;//(internal->sub_range / 2L) / internal->mclk; derot_freq = internal->derot_freq; do { @@ -426,6 +474,7 @@ static enum stb0899_status stb0899_searc return internal->status; } +#if 0 /* * stb0899_check_range * check if the found frequency is in the correct range @@ -477,6 +526,7 @@ static void next_sub_range(struct stb089 internal->freq = params->freq + (internal->sub_dir * internal->tuner_offst) / 1000; internal->sub_dir = -internal->sub_dir; } +#endif /* * stb0899_dvbs_algo @@ -494,6 +544,7 @@ enum stb0899_status stb0899_dvbs_algo(st u8 eq_const[10]; s32 clnI = 3; u32 bandwidth = 0; + int count; /* BETA values rated @ 99MHz */ s32 betaTab[5][4] = { @@ -571,7 +622,9 @@ enum stb0899_status stb0899_dvbs_algo(st stb0899_write_reg(state, STB0899_EQON, 0x01); /* Equalizer OFF while acquiring */ stb0899_write_reg(state, STB0899_VITSYNC, 0x19); - stb0899_first_subrange(state); + /* start where the user told us.... */ + internal->freq = params->freq; + count = 0; do { /* Initialisations */ cfr[0] = cfr[1] = 0; @@ -589,7 +642,7 @@ enum stb0899_status stb0899_dvbs_algo(st stb0899_i2c_gate_ctrl(&state->frontend, 1); /* Move tuner to frequency */ - dprintk(state->verbose, FE_DEBUG, 1, "Tuner set frequency"); + dprintk(state->verbose, FE_DEBUG, 1, "Tuner set frequency: %d", internal->freq); if (state->config->tuner_set_frequency) state->config->tuner_set_frequency(&state->frontend, internal->freq); @@ -617,7 +670,7 @@ enum stb0899_status stb0899_dvbs_algo(st "TIMING OK ! Derot freq=%d, mclk=%d", internal->derot_freq, internal->mclk); - if (stb0899_search_carrier(state) == CARRIEROK) { /* Search for carrier */ + if (stb0899_check_carrier(state) == CARRIEROK) { /* Check for carrier */ dprintk(state->verbose, FE_DEBUG, 1, "CARRIER OK ! Derot freq=%d, mclk=%d", internal->derot_freq, internal->mclk); @@ -627,12 +680,13 @@ enum stb0899_status stb0899_dvbs_algo(st "DATA OK ! Derot freq=%d, mclk=%d", internal->derot_freq, internal->mclk); - if (stb0899_check_range(state) == RANGEOK) { + internal->status = RANGEOK; dprintk(state->verbose, FE_DEBUG, 1, "RANGE OK ! derot freq=%d, mclk=%d", internal->derot_freq, internal->mclk); - internal->freq = params->freq + ((internal->derot_freq * internal->mclk) / 1000); + dprintk(state->verbose, FE_DEBUG, 1, "derot=%d user_freq=%d\n", internal->derot_freq, params->freq); + internal->freq = params->freq + stb0899_get_frequency_offset(state); reg = stb0899_read_reg(state, STB0899_PLPARM); internal->fecrate = STB0899_GETFIELD(VITCURPUN, reg); dprintk(state->verbose, FE_DEBUG, 1, @@ -642,14 +696,13 @@ enum stb0899_status stb0899_dvbs_algo(st dprintk(state->verbose, FE_DEBUG, 1, "internal puncture rate=%d", internal->fecrate); - } } } } - if (internal->status != RANGEOK) - next_sub_range(state); - } while (internal->sub_range && internal->status != RANGEOK); + /* avoid infinite loop */ + count++; + } while (count < 3 && internal->status != RANGEOK); /* Set the timing loop to tracking */ stb0899_write_reg(state, STB0899_RTC, 0x33); @@ -1491,16 +1544,8 @@ enum stb0899_status stb0899_dvbs2_algo(s STB0899_SETFIELD_VAL(EQ_SHIFT, reg, 0x02); stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQ_CNTRL, STB0899_OFF0_EQ_CNTRL, reg); - /* Store signal parameters */ - offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ); - - offsetfreq = offsetfreq / ((1 << 30) / 1000); - offsetfreq *= (internal->master_clk / 1000000); - reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2); - if (STB0899_GETFIELD(SPECTRUM_INVERT, reg)) - offsetfreq *= -1; - - internal->freq = internal->freq - offsetfreq; + /* store acutal frequency */ + internal->freq = internal->freq + stb0899_get_frequency_offset(state); internal->srate = stb0899_dvbs2_get_srate(state); reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2); diff -r fbcc9fa65f56 linux/drivers/media/dvb/frontends/stb0899_drv.c --- a/linux/drivers/media/dvb/frontends/stb0899_drv.c Wed May 28 12:08:48 2008 +0400 +++ b/linux/drivers/media/dvb/frontends/stb0899_drv.c Sun Jun 15 11:37:56 2008 +0200 @@ -1718,6 +1718,7 @@ static enum dvbfe_search stb0899_search( return DVBFE_ALGO_SEARCH_ERROR; } +#if 0 static enum stb0899_status stb0899_track_carrier(struct stb0899_state *state) { u8 reg; @@ -1906,6 +1907,8 @@ static int stb0899_get_modcod(struct stb return 0; } +#endif + /* * stb0899_track * periodically check the signal level against a specified @@ -1992,6 +1995,8 @@ static int stb0899_get_params(struct dvb { struct stb0899_state *state = fe->demodulator_priv; struct stb0899_internal *internal = &state->internal; + struct stb0899_params *intparams = &state->params; + params->frequency = internal->freq; params->inversion = internal->inversion; @@ -1999,6 +2004,7 @@ static int stb0899_get_params(struct dvb switch (state->delsys) { case DVBFE_DELSYS_DVBS: dprintk(verbose, FE_DEBUG, 1, "Get DVB-S params"); + params->frequency = intparams->freq + stb0899_get_frequency_offset(state); params->delsys.dvbs.symbol_rate = internal->srate; params->delsys.dvbs.modulation = DVBFE_MOD_QPSK; break; @@ -2009,6 +2015,9 @@ static int stb0899_get_params(struct dvb break; case DVBFE_DELSYS_DVBS2: dprintk(verbose, FE_DEBUG, 1, "Get DVB-S2 params"); + + params->frequency = intparams->freq + stb0899_get_frequency_offset(state); + params->delsys.dvbs2.symbol_rate = internal->srate; break; default: diff -r fbcc9fa65f56 linux/drivers/media/dvb/frontends/stb0899_priv.h --- a/linux/drivers/media/dvb/frontends/stb0899_priv.h Wed May 28 12:08:48 2008 +0400 +++ b/linux/drivers/media/dvb/frontends/stb0899_priv.h Sun Jun 15 11:37:56 2008 +0200 @@ -165,13 +165,11 @@ struct stb0899_params { struct stb0899_internal { u32 master_clk; - u32 freq; /* Demod internal Frequency */ + u32 freq; /* Demod internal Frequency (kHz) */ u32 srate; /* Demod internal Symbol rate */ enum stb0899_fec fecrate; /* Demod internal FEC rate */ - u32 srch_range; /* Demod internal Search Range */ - u32 sub_range; /* Demod current sub range (Hz) */ + u32 srch_range; /* Demod internal Search Range (Hz) */ u32 tuner_step; /* Tuner step (Hz) */ - u32 tuner_offst; /* Relative offset to carrier (Hz) */ u32 tuner_bw; /* Current bandwidth of the tuner (Hz) */ s32 mclk; /* Masterclock Divider factor (binary) */ @@ -184,7 +182,6 @@ struct stb0899_internal { s16 derot_step; /* Derotator step (binary value) */ s16 t_derot; /* Derotator time constant (ms) */ s16 t_data; /* Data recovery time constant (ms) */ - s16 sub_dir; /* Direction of the next sub range */ s16 t_agc1; /* Agc1 time constant (ms) */ s16 t_agc2; /* Agc2 time constant (ms) */ @@ -270,5 +267,11 @@ extern enum stb0899_status stb0899_dvbs_ extern enum stb0899_status stb0899_dvbs_algo(struct stb0899_state *state); extern enum stb0899_status stb0899_dvbs2_algo(struct stb0899_state *state); extern long stb0899_carr_width(struct stb0899_state *state); +/* + * read offset registers and + * calculate frequency offset in kHz + * according to the currently selected standard + */ +extern s32 stb0899_get_frequency_offset(struct stb0899_state *state); #endif //__STB0899_PRIV_H