in dvb-frontends/dib8000.c [3017:3368]
static int dib8000_tune(struct dvb_frontend *fe)
{
struct dib8000_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
enum frontend_tune_state *tune_state = &state->tune_state;
u16 locks, deeper_interleaver = 0, i;
int ret = 1; /* 1 symbol duration (in 100us unit) delay most of the time */
unsigned long *timeout = &state->timeout;
unsigned long now = jiffies;
u16 init_prbs;
#ifdef DIB8000_AGC_FREEZE
u16 agc1, agc2;
#endif
u32 corm[4] = {0, 0, 0, 0};
u8 find_index, max_value;
#if 0
if (*tune_state < CT_DEMOD_STOP)
dprintk("IN: context status = %d, TUNE_STATE %d autosearch step = %u jiffies = %lu\n",
state->channel_parameters_set, *tune_state, state->autosearch_state, now);
#endif
switch (*tune_state) {
case CT_DEMOD_START: /* 30 */
dib8000_reset_stats(fe);
if (state->revision == 0x8090)
dib8090p_init_sdram(state);
state->status = FE_STATUS_TUNE_PENDING;
state->channel_parameters_set = is_manual_mode(c);
dprintk("Tuning channel on %s search mode\n",
state->channel_parameters_set ? "manual" : "auto");
dib8000_viterbi_state(state, 0); /* force chan dec in restart */
/* Layer monitor */
dib8000_write_word(state, 285, dib8000_read_word(state, 285) & 0x60);
dib8000_set_frequency_offset(state);
dib8000_set_bandwidth(fe, c->bandwidth_hz / 1000);
if (state->channel_parameters_set == 0) { /* The channel struct is unknown, search it ! */
#ifdef DIB8000_AGC_FREEZE
if (state->revision != 0x8090) {
state->agc1_max = dib8000_read_word(state, 108);
state->agc1_min = dib8000_read_word(state, 109);
state->agc2_max = dib8000_read_word(state, 110);
state->agc2_min = dib8000_read_word(state, 111);
agc1 = dib8000_read_word(state, 388);
agc2 = dib8000_read_word(state, 389);
dib8000_write_word(state, 108, agc1);
dib8000_write_word(state, 109, agc1);
dib8000_write_word(state, 110, agc2);
dib8000_write_word(state, 111, agc2);
}
#endif
state->autosearch_state = AS_SEARCHING_FFT;
state->found_nfft = TRANSMISSION_MODE_AUTO;
state->found_guard = GUARD_INTERVAL_AUTO;
*tune_state = CT_DEMOD_SEARCH_NEXT;
} else { /* we already know the channel struct so TUNE only ! */
state->autosearch_state = AS_DONE;
*tune_state = CT_DEMOD_STEP_3;
}
state->symbol_duration = dib8000_get_symbol_duration(state);
break;
case CT_DEMOD_SEARCH_NEXT: /* 51 */
dib8000_autosearch_start(fe);
if (state->revision == 0x8090)
ret = 50;
else
ret = 15;
*tune_state = CT_DEMOD_STEP_1;
break;
case CT_DEMOD_STEP_1: /* 31 */
switch (dib8000_autosearch_irq(fe)) {
case 1: /* fail */
state->status = FE_STATUS_TUNE_FAILED;
state->autosearch_state = AS_DONE;
*tune_state = CT_DEMOD_STOP; /* else we are done here */
break;
case 2: /* Success */
state->status = FE_STATUS_FFT_SUCCESS; /* signal to the upper layer, that there was a channel found and the parameters can be read */
*tune_state = CT_DEMOD_STEP_3;
if (state->autosearch_state == AS_SEARCHING_GUARD)
*tune_state = CT_DEMOD_STEP_2;
else
state->autosearch_state = AS_DONE;
break;
case 3: /* Autosearch FFT max correlation endded */
*tune_state = CT_DEMOD_STEP_2;
break;
}
break;
case CT_DEMOD_STEP_2:
switch (state->autosearch_state) {
case AS_SEARCHING_FFT:
/* searching for the correct FFT */
if (state->revision == 0x8090) {
corm[2] = (dib8000_read_word(state, 596) << 16) | (dib8000_read_word(state, 597));
corm[1] = (dib8000_read_word(state, 598) << 16) | (dib8000_read_word(state, 599));
corm[0] = (dib8000_read_word(state, 600) << 16) | (dib8000_read_word(state, 601));
} else {
corm[2] = (dib8000_read_word(state, 594) << 16) | (dib8000_read_word(state, 595));
corm[1] = (dib8000_read_word(state, 596) << 16) | (dib8000_read_word(state, 597));
corm[0] = (dib8000_read_word(state, 598) << 16) | (dib8000_read_word(state, 599));
}
/* dprintk("corm fft: %u %u %u\n", corm[0], corm[1], corm[2]); */
max_value = 0;
for (find_index = 1 ; find_index < 3 ; find_index++) {
if (corm[max_value] < corm[find_index])
max_value = find_index ;
}
switch (max_value) {
case 0:
state->found_nfft = TRANSMISSION_MODE_2K;
break;
case 1:
state->found_nfft = TRANSMISSION_MODE_4K;
break;
case 2:
default:
state->found_nfft = TRANSMISSION_MODE_8K;
break;
}
/* dprintk("Autosearch FFT has found Mode %d\n", max_value + 1); */
*tune_state = CT_DEMOD_SEARCH_NEXT;
state->autosearch_state = AS_SEARCHING_GUARD;
if (state->revision == 0x8090)
ret = 50;
else
ret = 10;
break;
case AS_SEARCHING_GUARD:
/* searching for the correct guard interval */
if (state->revision == 0x8090)
state->found_guard = dib8000_read_word(state, 572) & 0x3;
else
state->found_guard = dib8000_read_word(state, 570) & 0x3;
/* dprintk("guard interval found=%i\n", state->found_guard); */
*tune_state = CT_DEMOD_STEP_3;
break;
default:
/* the demod should never be in this state */
state->status = FE_STATUS_TUNE_FAILED;
state->autosearch_state = AS_DONE;
*tune_state = CT_DEMOD_STOP; /* else we are done here */
break;
}
break;
case CT_DEMOD_STEP_3: /* 33 */
dib8000_set_isdbt_loop_params(state, LOOP_TUNE_1);
dib8000_set_isdbt_common_channel(state, 0, 0);/* setting the known channel parameters here */
*tune_state = CT_DEMOD_STEP_4;
break;
case CT_DEMOD_STEP_4: /* (34) */
dib8000_demod_restart(state);
dib8000_set_sync_wait(state);
dib8000_set_diversity_in(state->fe[0], state->diversity_onoff);
locks = (dib8000_read_word(state, 180) >> 6) & 0x3f; /* P_coff_winlen ? */
/* coff should lock over P_coff_winlen ofdm symbols : give 3 times this length to lock */
*timeout = dib8000_get_timeout(state, 2 * locks, SYMBOL_DEPENDENT_ON);
*tune_state = CT_DEMOD_STEP_5;
break;
case CT_DEMOD_STEP_5: /* (35) */
locks = dib8000_read_lock(fe);
if (locks & (0x3 << 11)) { /* coff-lock and off_cpil_lock achieved */
dib8000_update_timf(state); /* we achieved a coff_cpil_lock - it's time to update the timf */
if (!state->differential_constellation) {
/* 2 times lmod4_win_len + 10 symbols (pipe delay after coff + nb to compute a 1st correlation) */
*timeout = dib8000_get_timeout(state, (20 * ((dib8000_read_word(state, 188)>>5)&0x1f)), SYMBOL_DEPENDENT_ON);
*tune_state = CT_DEMOD_STEP_7;
} else {
*tune_state = CT_DEMOD_STEP_8;
}
} else if (time_after(now, *timeout)) {
*tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */
}
break;
case CT_DEMOD_STEP_6: /* (36) if there is an input (diversity) */
if ((state->fe[1] != NULL) && (state->output_mode != OUTMODE_DIVERSITY)) {
/* if there is a diversity fe in input and this fe is has not already failed : wait here until this this fe has succedeed or failed */
if (dib8000_get_status(state->fe[1]) <= FE_STATUS_STD_SUCCESS) /* Something is locked on the input fe */
*tune_state = CT_DEMOD_STEP_8; /* go for mpeg */
else if (dib8000_get_status(state->fe[1]) >= FE_STATUS_TUNE_TIME_TOO_SHORT) { /* fe in input failed also, break the current one */
*tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */
dib8000_viterbi_state(state, 1); /* start viterbi chandec */
dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
state->status = FE_STATUS_TUNE_FAILED;
}
} else {
dib8000_viterbi_state(state, 1); /* start viterbi chandec */
dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
*tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */
state->status = FE_STATUS_TUNE_FAILED;
}
break;
case CT_DEMOD_STEP_7: /* 37 */
locks = dib8000_read_lock(fe);
if (locks & (1<<10)) { /* lmod4_lock */
ret = 14; /* wait for 14 symbols */
*tune_state = CT_DEMOD_STEP_8;
} else if (time_after(now, *timeout))
*tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */
break;
case CT_DEMOD_STEP_8: /* 38 */
dib8000_viterbi_state(state, 1); /* start viterbi chandec */
dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
/* mpeg will never lock on this condition because init_prbs is not set : search for it !*/
if (c->isdbt_sb_mode
&& c->isdbt_sb_subchannel < 14
&& !state->differential_constellation) {
state->subchannel = 0;
*tune_state = CT_DEMOD_STEP_11;
} else {
*tune_state = CT_DEMOD_STEP_9;
state->status = FE_STATUS_LOCKED;
}
break;
case CT_DEMOD_STEP_9: /* 39 */
if ((state->revision == 0x8090) || ((dib8000_read_word(state, 1291) >> 9) & 0x1)) { /* fe capable of deinterleaving : esram */
/* defines timeout for mpeg lock depending on interleaver length of longest layer */
for (i = 0; i < 3; i++) {
if (c->layer[i].interleaving >= deeper_interleaver) {
dprintk("layer%i: time interleaver = %d\n", i, c->layer[i].interleaving);
if (c->layer[i].segment_count > 0) { /* valid layer */
deeper_interleaver = c->layer[0].interleaving;
state->longest_intlv_layer = i;
}
}
}
if (deeper_interleaver == 0)
locks = 2; /* locks is the tmp local variable name */
else if (deeper_interleaver == 3)
locks = 8;
else
locks = 2 * deeper_interleaver;
if (state->diversity_onoff != 0) /* because of diversity sync */
locks *= 2;
*timeout = now + msecs_to_jiffies(200 * locks); /* give the mpeg lock 800ms if sram is present */
dprintk("Deeper interleaver mode = %d on layer %d : timeout mult factor = %d => will use timeout = %ld\n",
deeper_interleaver, state->longest_intlv_layer, locks, *timeout);
*tune_state = CT_DEMOD_STEP_10;
} else
*tune_state = CT_DEMOD_STOP;
break;
case CT_DEMOD_STEP_10: /* 40 */
locks = dib8000_read_lock(fe);
if (locks&(1<<(7-state->longest_intlv_layer))) { /* mpeg lock : check the longest one */
dprintk("ISDB-T layer locks: Layer A %s, Layer B %s, Layer C %s\n",
c->layer[0].segment_count ? (locks >> 7) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled",
c->layer[1].segment_count ? (locks >> 6) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled",
c->layer[2].segment_count ? (locks >> 5) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled");
if (c->isdbt_sb_mode
&& c->isdbt_sb_subchannel < 14
&& !state->differential_constellation)
/* signal to the upper layer, that there was a channel found and the parameters can be read */
state->status = FE_STATUS_DEMOD_SUCCESS;
else
state->status = FE_STATUS_DATA_LOCKED;
*tune_state = CT_DEMOD_STOP;
} else if (time_after(now, *timeout)) {
if (c->isdbt_sb_mode
&& c->isdbt_sb_subchannel < 14
&& !state->differential_constellation) { /* continue to try init prbs autosearch */
state->subchannel += 3;
*tune_state = CT_DEMOD_STEP_11;
} else { /* we are done mpeg of the longest interleaver xas not locking but let's try if an other layer has locked in the same time */
if (locks & (0x7 << 5)) {
dprintk("Not all ISDB-T layers locked in %d ms: Layer A %s, Layer B %s, Layer C %s\n",
jiffies_to_msecs(now - *timeout),
c->layer[0].segment_count ? (locks >> 7) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled",
c->layer[1].segment_count ? (locks >> 6) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled",
c->layer[2].segment_count ? (locks >> 5) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled");
state->status = FE_STATUS_DATA_LOCKED;
} else
state->status = FE_STATUS_TUNE_FAILED;
*tune_state = CT_DEMOD_STOP;
}
}
break;
case CT_DEMOD_STEP_11: /* 41 : init prbs autosearch */
init_prbs = dib8000_get_init_prbs(state, state->subchannel);
if (init_prbs) {
dib8000_set_subchannel_prbs(state, init_prbs);
*tune_state = CT_DEMOD_STEP_9;
} else {
*tune_state = CT_DEMOD_STOP;
state->status = FE_STATUS_TUNE_FAILED;
}
break;
default:
break;
}
/* tuning is finished - cleanup the demod */
switch (*tune_state) {
case CT_DEMOD_STOP: /* (42) */
#ifdef DIB8000_AGC_FREEZE
if ((state->revision != 0x8090) && (state->agc1_max != 0)) {
dib8000_write_word(state, 108, state->agc1_max);
dib8000_write_word(state, 109, state->agc1_min);
dib8000_write_word(state, 110, state->agc2_max);
dib8000_write_word(state, 111, state->agc2_min);
state->agc1_max = 0;
state->agc1_min = 0;
state->agc2_max = 0;
state->agc2_min = 0;
}
#endif
ret = 0;
break;
default:
break;
}
if ((ret > 0) && (*tune_state > CT_DEMOD_STEP_3))
return ret * state->symbol_duration;
if ((ret > 0) && (ret < state->symbol_duration))
return state->symbol_duration; /* at least one symbol */
return ret;
}