diff --git a/ddbridge/ddbridge-sx8.c b/ddbridge/ddbridge-sx8.c index cf91cbe..27ee012 100644 --- a/ddbridge/ddbridge-sx8.c +++ b/ddbridge/ddbridge-sx8.c @@ -56,6 +56,7 @@ struct sx8_base { struct sx8 { struct mci mci; + struct mutex lock; int first_time_lock; int started; @@ -123,38 +124,45 @@ static int ddb_mci_tsconfig(struct mci *state, u32 config) static int read_status(struct dvb_frontend *fe, enum fe_status *status) { - int stat; + int stat = 0; struct sx8 *state = fe->demodulator_priv; struct mci_base *mci_base = state->mci.base; struct sx8_base *sx8_base = (struct sx8_base *) mci_base; struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct mci_result res; + *status = 0x00; + mutex_lock(&state->lock); + if (!state->started && !state->iq_started) + goto unlock; stat = ddb_mci_get_status(&state->mci, &res); if (stat) - return stat; - if (sx8_base->iq_mode >= 2) { - *status = 0x1f; - return stat; - } - *status = 0x00; + goto unlock; ddb_mci_get_info(&state->mci); - if (res.status == SX8_DEMOD_WAIT_MATYPE) - *status = 0x0f; - if (res.status == MCI_DEMOD_LOCKED) { - *status = 0x1f; - if (state->mci.signal_info.dvbs2_signal_info.standard == 2) { + if (stat) + goto unlock; + if (res.status == MCI_DEMOD_LOCKED || res.status == SX8_DEMOD_IQ_MODE) { + *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | + FE_HAS_CARRIER | FE_HAS_SIGNAL; + if (res.status == MCI_DEMOD_LOCKED) { mutex_lock(&mci_base->tuner_lock); - if (state->started) - sx8_base->used_ldpc_bitrate[state->mci.nr] = - p->symbol_rate * - dvbs2_bits_per_symbol[ - state->mci.signal_info. - dvbs2_signal_info.pls_code]; + if (state->first_time_lock && state->started) { + if (state->mci.signal_info.dvbs2_signal_info.standard == 2) { + sx8_base->used_ldpc_bitrate[state->mci.nr] = + p->symbol_rate * + dvbs2_bits_per_symbol[ + state->mci.signal_info. + dvbs2_signal_info.pls_code]; + } else + sx8_base->used_ldpc_bitrate[state->mci.nr] = 0; + state->first_time_lock = 0; + } mutex_unlock(&mci_base->tuner_lock); - } else - sx8_base->used_ldpc_bitrate[state->mci.nr] = 0; - } + } + else if (res.status >= SX8_DEMOD_WAIT_MATYPE) + *status = FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL; +unlock: + mutex_unlock(&state->lock); return stat; } @@ -197,9 +205,9 @@ static int stop_iq(struct dvb_frontend *fe) state->mci.demod = SX8_DEMOD_NONE; } sx8_base->used_ldpc_bitrate[state->mci.nr] = 0; + mutex_unlock(&mci_base->tuner_lock); sx8_base->iq_mode = 0; state->iq_started = 0; - mutex_unlock(&mci_base->tuner_lock); return 0; } @@ -209,12 +217,13 @@ static int stop(struct dvb_frontend *fe) struct mci_base *mci_base = state->mci.base; struct sx8_base *sx8_base = (struct sx8_base *) mci_base; struct mci_command cmd; - u32 input = state->mci.tuner; + u32 input; + input = state->mci.tuner; if (!state->started) return -1; - memset(&cmd, 0, sizeof(cmd)); if (state->mci.demod != SX8_DEMOD_NONE) { + memset(&cmd, 0, sizeof(cmd)); cmd.command = MCI_CMD_STOP; cmd.demod = state->mci.demod; ddb_mci_cmd(&state->mci, &cmd, NULL); @@ -236,8 +245,8 @@ static int stop(struct dvb_frontend *fe) } sx8_base->used_ldpc_bitrate[state->mci.nr] = 0; sx8_base->iq_mode = 0; - mutex_unlock(&mci_base->tuner_lock); state->started = 0; + mutex_unlock(&mci_base->tuner_lock); return 0; } @@ -308,16 +317,15 @@ static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config) free_ldpc_bitrate = MAX_LDPC_BITRATE - used_ldpc_bitrate; if (free_ldpc_bitrate > MAX_DEMOD_LDPC_BITRATE) free_ldpc_bitrate = MAX_DEMOD_LDPC_BITRATE; - + while (p->symbol_rate * bits_per_symbol > free_ldpc_bitrate) bits_per_symbol--; if (bits_per_symbol < 2) { stat = -EBUSY; goto unlock; } - modmask &= ((1 << (bits_per_symbol - 1)) - 1); - if( ((flags & 0x02) != 0) && (modmask == 0)) { + if (((flags & 0x02) != 0) && (modmask == 0)) { stat = -EBUSY; goto unlock; } @@ -343,11 +351,10 @@ unlock: if (stat) return stat; memset(&cmd, 0, sizeof(cmd)); - if (sx8_base->iq_mode) { cmd.command = SX8_CMD_ENABLE_IQOUTPUT; cmd.demod = state->mci.demod; - cmd.output = p->stream_id & 7; + cmd.output = p->stream_id & 0x0f; ddb_mci_cmd(&state->mci, &cmd, NULL); ddb_mci_tsconfig(&state->mci, ts_config); } @@ -377,6 +384,9 @@ unlock: (p->stream_id & 0x80000000)) cmd.output |= 0x80; stat = ddb_mci_cmd(&state->mci, &cmd, NULL); + state->started = 1; + state->first_time_lock = 1; + state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL; if (stat) stop(fe); return stat; @@ -395,8 +405,8 @@ static int start_iq(struct dvb_frontend *fe, u32 flags, u32 input = state->mci.tuner; int i, stat = 0; + mutex_lock(&mci_base->tuner_lock); if (!state->iq_started) { - mutex_lock(&mci_base->tuner_lock); if (sx8_base->iq_mode) { stat = -EBUSY; goto unlock; @@ -409,17 +419,18 @@ static int start_iq(struct dvb_frontend *fe, u32 flags, goto unlock; } state->mci.demod = 0; - /* - if (!sx8_base->tuner_use_count[input]) - mci_set_tuner(fe, input, 1); - */ sx8_base->tuner_use_count[input]++; sx8_base->iq_mode = 2; - unlock: - mutex_unlock(&mci_base->tuner_lock); - if (stat) - return stat; + } else { + if ((state->iq_started & 0x07) != state->mci.nr) { + stat = -EBUSY; + goto unlock; + } } +unlock: + mutex_unlock(&mci_base->tuner_lock); + if (stat) + return stat; mci_set_tuner(fe, input, 1, flags & 0xff, 0); memset(&cmd, 0, sizeof(cmd)); cmd.command = SX8_CMD_START_IQ; @@ -431,6 +442,9 @@ static int start_iq(struct dvb_frontend *fe, u32 flags, cmd.tuner = state->mci.tuner; cmd.demod = state->mci.demod; stat = ddb_mci_cmd(&state->mci, &cmd, NULL); + state->iq_started = 8 | state->mci.nr; + state->first_time_lock = 1; + state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL; if (stat) stop_iq(fe); ddb_mci_tsconfig(&state->mci, ts_config); @@ -443,7 +457,6 @@ static int set_lna(struct dvb_frontend *fe) return 0; } - static int set_parameters(struct dvb_frontend *fe) { int stat = 0; @@ -459,6 +472,7 @@ static int set_parameters(struct dvb_frontend *fe) state->mci.input->con = ts_mode << 8; if (iq_mode) ts_config = (SX8_TSCONFIG_TSHEADER | SX8_TSCONFIG_MODE_IQ); + mutex_lock(&state->lock); stop(fe); if (iq_mode < 2) { u32 mask; @@ -485,19 +499,10 @@ static int set_parameters(struct dvb_frontend *fe) break; } stat = start(fe, 3, mask, ts_config); - if (!stat) { - state->started = 1; - state->first_time_lock = 1; - state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL; - } } else { stat = start_iq(fe, isi & 0xffffff, 4, ts_config); - if (!stat) { - state->iq_started = 1; - state->first_time_lock = 1; - state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL; - } } + mutex_unlock(&state->lock); return stat; } @@ -536,16 +541,22 @@ static int set_input(struct dvb_frontend *fe, int input) return -EINVAL; if (state->mci.tuner == input) return 0; + mutex_lock(&state->lock); stop_iq(fe); stop(fe); state->mci.tuner = p->input = input; + mutex_unlock(&state->lock); return 0; } static int sleep(struct dvb_frontend *fe) { + struct sx8 *state = fe->demodulator_priv; + + mutex_lock(&state->lock); stop_iq(fe); stop(fe); + mutex_unlock(&state->lock); return 0; } @@ -591,6 +602,7 @@ static int init(struct mci *mci) state->mci.demod = SX8_DEMOD_NONE; mci->fe.ops.xbar[1] = mci->nr; mci->fe.dtv_property_cache.input = mci->tuner; + mutex_init(&state->lock); return 0; }