diff --git a/ddbridge/ddbridge-mci.h b/ddbridge/ddbridge-mci.h index 8a555f7..2c0d274 100644 --- a/ddbridge/ddbridge-mci.h +++ b/ddbridge/ddbridge-mci.h @@ -114,7 +114,7 @@ #define MCI_CMD_STOP (0x01) #define MCI_CMD_GETSTATUS (0x02) #define MCI_CMD_GETSIGNALINFO (0x03) -#define MCI_CMD_RFPOWER (0x04) +//#define MCI_CMD_RFPOWER (0x04) #define MCI_CMD_SEARCH_DVBS (0x10) #define MCI_CMD_SEARCH_ISDBS (0x11) @@ -180,6 +180,12 @@ #define M4_SIGNALINFO_FLAG_CHANGE (0x01) #define M4_SIGNALINFO_FLAG_EWS (0x02) +#define SX8_ROLLOFF_25 1 +#define SX8_ROLLOFF_20 2 +#define SX8_ROLLOFF_15 5 +#define SX8_ROLLOFF_10 3 +#define SX8_ROLLOFF_05 4 + #define MCI_SUCCESS(status) ((status & MCI_STATUS_UNSUPPORTED) == 0) @@ -298,20 +304,27 @@ struct mci_command { u16 point; } get_iq_symbol; + struct { - u8 flags; /* Bit 0 : 1 = VTM, 0 = SCAN. Bit 1: Set Gain */ - u8 roll_off; - u8 rsvd1; - u8 rsvd2; - u32 frequency; - u32 symbol_rate; /* Only in VTM (versatile tuner mode). */ - u16 gain; + uint8_t flags; /* Bit 0 : 0 = VTM/SDR, 1 = SCAN, Bit 1: Disable AGC, Bit 2: Set Gain */ + uint8_t roll_off; + uint8_t rsvd1; + uint8_t rsvd2; + uint32_t frequency; + uint32_t symbol_rate; /* Only in VTM/SDR mode, SCAN Mode uses exactly 1550/24 MSymbols/s.*/ + uint8_t gain; /* Gain in 0.25 dB Steps */ + /* Frequency, symbolrate and gain can be schanged while running */ } sx8_start_iq; struct { - /* Bit 1:0 = STVVGLNA Gain. 0 = AGC, 1 = 0dB, - 2 = Minimum, 3 = Maximum */ - u8 flags; + uint8_t flags; + /* Bit 0:1 Preamp Mode; 0 = Preamp AGC, 1 == Minimum (~ -17dB) , + 2 = Medium, 3 = Maximum gain {~ 15dB} + Bit 2: Bypass Input LNA (6 dB less gain) (Note this is after Preamp) + Bit 4: Set RF Gain + Bit 5: Freeze RF Gain (Turn AGC off at current gain, only when already enabled) + Bit 7: Optimize RF Gain and freeze for FFT */ + uint8_t rf_gain; /* 0 .. 50 dB */ } sx8_input_enable; struct { @@ -362,8 +375,8 @@ struct mci_result { struct { u8 standard; /* 1 = DVB-S, 2 = DVB-S2X */ - u8 pls_code; /* puncture rate for DVB-S */ - u8 roll_off; /* 2-0: rolloff */ + u8 pls_code; /* PLS code for DVB-S2/S2X, puncture rate for DVB-S */ + u8 roll_off; /* 2-0: rolloff, 7: spectrum inversion */ u8 flags; u32 frequency; /* actual frequency in Hz */ u32 symbol_rate; /* actual symbolrate in Hz */ @@ -396,8 +409,6 @@ struct mci_result { u8 modulation2; // bit 7..5: CodeRate Low, bit 4..3 Guard Interval, bit 2..1 FFT Mode u8 Rsvd0; u8 Flags; - //u16 tps_cell_id; /* Cell Identifier */ - u32 frequency; /* actual frequency in Hz */ u32 rsvd1; s16 channel_power; /* channel power in dBm x 100 */ @@ -497,6 +508,7 @@ struct mci_result { struct { u8 TPSInfo[7]; + // uint16_t TPS_CellID; // Cell Identifier } DVBT_TPSInfo; struct { @@ -651,7 +663,11 @@ struct mci_result { u8 Extension[8]; // 61 bits, right aligned } ISDBS_TMCCInfo; }; - u32 version[4]; + u32 version[3]; + u32 version_rsvd; + u8 version_major; + u8 version_minor; + u8 version_sub; }; diff --git a/ddbridge/ddbridge-sx8.c b/ddbridge/ddbridge-sx8.c index a215784..d4a5626 100644 --- a/ddbridge/ddbridge-sx8.c +++ b/ddbridge/ddbridge-sx8.c @@ -31,7 +31,9 @@ module_param(default_mod, int, 0444); MODULE_PARM_DESC(default_mod, "default modulations enabled, default is 3 (1 = QPSK, 2 = 8PSK, 4 = 16APSK, ...)"); static const u32 MCLK = (1550000000 / 12); -static const u32 MAX_LDPC_BITRATE = (720000000); + +/* Add 2MBit/s overhead allowance (minimum factor is 90/32400 for QPSK w/o Pilots) */ +static const u32 MAX_LDPC_BITRATE = (720000000 + 2000000); static const u32 MAX_DEMOD_LDPC_BITRATE = (1550000000 / 6); #define SX8_TUNER_NUM 4 @@ -56,6 +58,7 @@ struct sx8 { int first_time_lock; int started; + int iq_started; u32 bb_mode; u32 local_frequency; @@ -156,6 +159,25 @@ static int mci_set_tuner(struct dvb_frontend *fe, u32 tuner, u32 on) return ddb_mci_cmd(&state->mci, &cmd, NULL); } +static int stop_iq(struct dvb_frontend *fe) +{ + 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 mci_command cmd; + u32 input = state->mci.tuner; + + if (!state->iq_started) + return -1; + memset(&cmd, 0, sizeof(cmd)); + cmd.command = SX8_CMD_STOP_IQ; + cmd.demod = state->mci.demod; + ddb_mci_cmd(&state->mci, &cmd, NULL); + ddb_mci_config(&state->mci, SX8_TSCONFIG_MODE_NORMAL); + state->iq_started = 0; + return 0; +} + static int stop(struct dvb_frontend *fe) { struct sx8 *state = fe->demodulator_priv; @@ -362,7 +384,7 @@ unlock: cmd.demod = state->mci.demod; stat = ddb_mci_cmd(&state->mci, &cmd, NULL); if (stat) - stop(fe); + stop_iq(fe); ddb_mci_config(&state->mci, ts_config); return stat; } @@ -374,16 +396,18 @@ static int set_parameters(struct dvb_frontend *fe) struct dtv_frontend_properties *p = &fe->dtv_property_cache; u32 ts_config = SX8_TSCONFIG_MODE_NORMAL, iq_mode = 0, isi; - stop(fe); + isi = p->stream_id; if (isi != NO_STREAM_ID_FILTER) { iq_mode = (isi & 0x30000000) >> 28; } if (iq_mode) ts_config = (SX8_TSCONFIG_TSHEADER | SX8_TSCONFIG_MODE_IQ); + stop(fe); if (iq_mode < 2) { u32 mask; + stop_iq(fe); switch (p->modulation) { case APSK_256: mask = 0x7f; @@ -405,13 +429,18 @@ 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, iq_mode & 1, 4, ts_config); - } - if (!stat) { - state->started = 1; - state->first_time_lock = 1; - state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL; + if (!stat) { + state->iq_started = 1; + state->first_time_lock = 1; + state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL; + } } return stat; } @@ -451,6 +480,7 @@ static int set_input(struct dvb_frontend *fe, int input) return -EINVAL; if (state->mci.tuner == input) return 0; + stop_iq(fe); stop(fe); state->mci.tuner = p->input = input; return 0; @@ -458,6 +488,7 @@ static int set_input(struct dvb_frontend *fe, int input) static int sleep(struct dvb_frontend *fe) { + stop_iq(fe); stop(fe); return 0; }