--- a/linux/drivers/media/dvb/frontends/stb0899_algo.c 2010-09-15 15:01:55.000000000 +0200 +++ b/linux/drivers/media/dvb/frontends/stb0899_algo.c 2010-09-17 16:05:01.000000000 +0200 @@ -1,7 +1,7 @@ /* STB0899 Multistandard Frontend driver + Copyright (C) Hans Ellenberger for Modifications Aug. 27, 2010 HE: Copyright (C) Manu Abraham (abraham.manu@gmail.com) - Copyright (C) ST Microelectronics This program is free software; you can redistribute it and/or modify @@ -31,8 +31,6 @@ return n; } -#if 0 /* keep */ -/* These functions are currently unused */ /* * stb0899_calc_srate * Compute symbol rate @@ -56,7 +54,7 @@ * stb0899_get_srate * Get the current symbol rate */ -static u32 stb0899_get_srate(struct stb0899_state *state) +u32 stb0899_get_srate(struct stb0899_state *state) { struct stb0899_internal *internal = &state->internal; u8 sfr[3]; @@ -65,7 +63,6 @@ return stb0899_calc_srate(internal->master_clk, sfr); } -#endif /* * stb0899_set_srate @@ -167,7 +164,7 @@ /* * stb0899_check_tmg - * check for timing lock + * check for timing lock for high rates (MCPC) * internal.Ttiming: time to wait for loop lock */ static enum stb0899_status stb0899_check_tmg(struct stb0899_state *state) @@ -201,39 +198,46 @@ /* * stb0899_search_tmg - * perform a fs/2 zig-zag to find timing + * perform a fs/2 zig-zag to find timing, called once only from below stb0899_dvbs_algo for low rates (SCPC) + * HE: In case this single attempt fails, the tuner gives up */ static enum stb0899_status stb0899_search_tmg(struct stb0899_state *state) { struct stb0899_internal *internal = &state->internal; - struct stb0899_params *params = &state->params; - - short int derot_step, derot_freq = 0, derot_limit, next_loop = 3; - int index = 0; + short int derot_step, derot_freq = 0, derot_limit, next_loop = 3; /* HE: 3 trials, then give up */ + int index = 0; /* HE: First trial at the exact frequency? */ u8 cfr[2]; internal->status = NOTIMING; /* timing loop computation & symbol rate optimisation */ derot_limit = (internal->sub_range / 2L) / internal->mclk; - derot_step = (params->srate / 2L) / internal->mclk; + derot_step = internal->derot_step * 4; /* dertot_step = decreasing delta */ - while ((stb0899_check_tmg(state) != TIMINGOK) && next_loop) { - index++; - derot_freq += index * internal->direction * derot_step; /* next derot zig zag position */ + dprintk(state->verbose, FE_DEBUG, 1, "search_tmg limit= %d, initial step= %d, mclk= %d", + derot_limit, derot_step, internal->mclk); + + while ((stb0899_check_tmg(state) != TIMINGOK) && next_loop) { /* Terminate when ok or when exhausted */ + + derot_freq += index * internal->direction * derot_step; /* next zigzag position, initially no delta */ + + dprintk(state->verbose, FE_DEBUG, 1, "index= %d, derot_freq= %d, limit= %d, direction= %d, step= %d", + index, derot_freq, derot_limit, internal->direction, derot_step); if (abs(derot_freq) > derot_limit) - next_loop--; + next_loop--; /* HE: Funny - Why decrease only if above limit ??? */ - if (next_loop) { + if (next_loop) { /* Setup tuner hardware frequency */ STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq)); STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq)); stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */ } + + index++; internal->direction = -internal->direction; /* Change zigzag direction */ } - if (internal->status == TIMINGOK) { + if (internal->status == TIMINGOK) { /* We got it */ stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency */ internal->derot_freq = state->config->inversion * MAKEWORD16(cfr[0], cfr[1]); dprintk(state->verbose, FE_DEBUG, 1, "------->TIMING OK ! Derot Freq = %d", internal->derot_freq); @@ -278,14 +282,21 @@ { struct stb0899_internal *internal = &state->internal; - short int derot_freq = 0, last_derot_freq = 0, derot_limit, next_loop = 3; + short int derot_freq = 0, last_derot_freq = 0, derot_limit, derot_step, next_loop = 3; int index = 0; + int base_freq; u8 cfr[2]; u8 reg; internal->status = NOCARRIER; derot_limit = (internal->sub_range / 2L) / internal->mclk; derot_freq = internal->derot_freq; + derot_step = internal->derot_step * 2; + last_derot_freq = internal->derot_freq; + base_freq = internal->derot_freq; + + dprintk(state->verbose, FE_DEBUG, 1, "search_carrier freq= %d, limit= %d, step= %d, mclk = %d", + derot_freq, derot_limit, derot_step, internal->mclk); reg = stb0899_read_reg(state, STB0899_CFD); STB0899_SETFIELD_VAL(CFD_ON, reg, 1); @@ -294,13 +305,17 @@ do { dprintk(state->verbose, FE_DEBUG, 1, "Derot Freq=%d, mclk=%d", derot_freq, internal->mclk); if (stb0899_check_carrier(state) == NOCARRIER) { - index++; + last_derot_freq = derot_freq; - derot_freq += index * internal->direction * internal->derot_step; /* next zig zag derotator position */ + derot_freq += index * internal->direction * derot_step; /* next zig zag derotator position */ - if(abs(derot_freq) > derot_limit) - next_loop--; + dprintk(state->verbose, FE_DEBUG, 1, "index = %d, derot_freq = %d, limit = %d, step = %d", + index, derot_freq, derot_limit, derot_step); + + // Alex: should limit based on initial base freq + if(derot_freq > base_freq + derot_limit || derot_freq < base_freq - derot_limit) + next_loop--; if (next_loop) { reg = stb0899_read_reg(state, STB0899_CFD); STB0899_SETFIELD_VAL(CFD_ON, reg, 1); @@ -310,9 +325,9 @@ STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq)); stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */ } - } - + index++; internal->direction = -internal->direction; /* Change zigzag direction */ + } } while ((internal->status != CARRIEROK) && next_loop); if (internal->status == CARRIEROK) { @@ -328,7 +342,7 @@ /* * stb0899_check_data - * Check for data found + * Check for data found. Called only from stb0899_search_data */ static enum stb0899_status stb0899_check_data(struct stb0899_state *state) { @@ -337,18 +351,18 @@ int lock = 0, index = 0, dataTime = 500, loop; u8 reg; - + msleep(1); // Alex: added sleep 5 mSec HE: 1ms internal->status = NODATA; /* RESET FEC */ reg = stb0899_read_reg(state, STB0899_TSTRES); STB0899_SETFIELD_VAL(FRESACS, reg, 1); stb0899_write_reg(state, STB0899_TSTRES, reg); - msleep(1); + msleep(1); // Alex: changed from 1 to 5 mSec HE: 1ms reg = stb0899_read_reg(state, STB0899_TSTRES); STB0899_SETFIELD_VAL(FRESACS, reg, 0); stb0899_write_reg(state, STB0899_TSTRES, reg); - + msleep(1); // Alex: added 5 mSec HE: 1ms if (params->srate <= 2000000) dataTime = 2000; else if (params->srate <= 5000000) @@ -360,6 +374,7 @@ stb0899_write_reg(state, STB0899_DSTATUS2, 0x00); /* force search loop */ while (1) { + msleep(1); // Alex: added 1 mSec /* WARNING! VIT LOCKED has to be tested before VIT_END_LOOOP */ reg = stb0899_read_reg(state, STB0899_VSTATUS); lock = STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg); @@ -380,27 +395,36 @@ /* * stb0899_search_data - * Search for a QPSK carrier with the derotator + * Search for a QPSK carrier with the derotator, called from stb0899_dvbs_algo for S1 only */ static enum stb0899_status stb0899_search_data(struct stb0899_state *state) { short int derot_freq, derot_step, derot_limit, next_loop = 3; u8 cfr[2]; u8 reg; - int index = 1; + int index = 0; + int base_freq; struct stb0899_internal *internal = &state->internal; - struct stb0899_params *params = &state->params; - derot_step = (params->srate / 4L) / internal->mclk; + derot_step = internal->derot_step; derot_limit = (internal->sub_range / 2L) / internal->mclk; derot_freq = internal->derot_freq; + base_freq = internal->derot_freq; + + dprintk(state->verbose, FE_DEBUG, 1, "limit = %d, step = %d, mclk = %d", + derot_limit, derot_step, internal->mclk); do { if ((internal->status != CARRIEROK) || (stb0899_check_data(state) != DATAOK)) { derot_freq += index * internal->direction * derot_step; /* next zig zag derotator position */ - if (abs(derot_freq) > derot_limit) + + dprintk(state->verbose, FE_DEBUG, 1, "index = %d, derot_freq = %d, limit = %d, direction = %d, step = %d", + index, derot_freq, derot_limit, internal->direction, derot_step); + + // Alex: should limit based on initial base freq + if(derot_freq > base_freq + derot_limit || derot_freq < base_freq - derot_limit) next_loop--; if (next_loop) { @@ -414,9 +438,10 @@ stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */ stb0899_check_carrier(state); - index++; } } + + index++; internal->direction = -internal->direction; /* change zig zag direction */ } while ((internal->status != DATAOK) && next_loop); @@ -481,7 +506,7 @@ internal->sub_dir = -internal->sub_dir; } -/* +/**** Main S1 tuning code. S2 is at the end *********************************************************************** * stb0899_dvbs_algo * Search for a signal, timing, carrier and data for a * given frequency in a given range @@ -538,7 +563,7 @@ clnI = 3; } - dprintk(state->verbose, FE_DEBUG, 1, "Set the timing loop to acquisition"); + dprintk(state->verbose, FE_DEBUG, 1, "S1: 27.8. Set the timing loop to acquisition"); /* Set the timing loop to acquisition */ stb0899_write_reg(state, STB0899_RTC, 0x46); stb0899_write_reg(state, STB0899_CFD, 0xee); @@ -554,7 +579,11 @@ /* Initial calculations */ internal->derot_step = internal->derot_percent * (params->srate / 1000L) / internal->mclk; /* DerotStep/1000 * Fsymbol */ - internal->t_derot = stb0899_calc_derot_time(params->srate); + + dprintk(state->verbose, FE_DEBUG, 1, "Derot step=%d", + internal->derot_step); + + internal->t_derot = stb0899_calc_derot_time(params->srate); /* Calc time according to srate */ internal->t_data = 500; dprintk(state->verbose, FE_DEBUG, 1, "RESET stream merger"); @@ -617,8 +646,8 @@ if (internal->status == TIMINGOK) { dprintk(state->verbose, FE_DEBUG, 1, - "TIMING OK ! Derot freq=%d, mclk=%d", - internal->derot_freq, internal->mclk); + "TIMING OK ! Derot freq=%d, mclk=%d, srate=%d", + internal->derot_freq, internal->mclk, params->srate); if (stb0899_search_carrier(state) == CARRIEROK) { /* Search for carrier */ dprintk(state->verbose, FE_DEBUG, 1, @@ -719,7 +748,7 @@ return internal->status; } -/* +/*** S2 codel below ************************************************************************************************** * stb0899_dvbs2_config_uwp * Configure UWP state machine */ @@ -766,7 +795,7 @@ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, reg); } -static long Log2Int(int number) +long Log2Int(int number) { int i; @@ -954,8 +983,13 @@ s32 crl_nom_freq; u32 reg; + dprintk(state->verbose, FE_DEBUG, 1, "carr_freq = %d, master_clk = %d", carr_freq, master_clk); + crl_nom_freq = (1 << config->crl_nco_bits) / master_clk; crl_nom_freq *= carr_freq; + + dprintk(state->verbose, FE_DEBUG, 1, "crl_nom_freq = %d", crl_nom_freq); + reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ); STB0899_SETFIELD_VAL(CRL_NOM_FREQ, reg, crl_nom_freq); stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_NOM_FREQ, STB0899_OFF0_CRL_NOM_FREQ, reg); @@ -1080,7 +1114,7 @@ /* * stb0899_dvbs2_get_dmd_status - * get DVB-S2 Demod LOCK status + * get DVB-S2 Demod LOCK status, wait max. timeout ms */ static enum stb0899_status stb0899_dvbs2_get_dmd_status(struct stb0899_state *state, int timeout) { @@ -1139,6 +1173,8 @@ { int time = 0, Locked; + dprintk(state->verbose, FE_DEBUG, 1, "timeout = %d", timeout); + do { Locked = stb0899_dvbs2_get_data_lock(state, 1); time++; @@ -1345,6 +1381,9 @@ FecLockTime = 20; /* 20 ms max time to lock FEC, 20Mbs< SYMB <= 25Mbs */ } + dprintk(state->verbose, FE_DEBUG, 1, "S2: srate= %d, searchTime= %d, FecLockTime= %d", + internal->srate, searchTime, FecLockTime); + /* Maintain Stream Merger in reset during acquisition */ reg = stb0899_read_reg(state, STB0899_TSTRES); STB0899_SETFIELD_VAL(FRESRS, reg, 1);