diff --git a/ddbridge/ddbridge-m4.c b/ddbridge/ddbridge-m4.c index 75b1d7e..88f0be0 100644 --- a/ddbridge/ddbridge-m4.c +++ b/ddbridge/ddbridge-m4.c @@ -27,24 +27,376 @@ #include "ddbridge-mci.h" struct m4_base { - struct mci_base mci_base; + struct mci_base mci_base; }; struct m4 { - struct mci mci; + struct mci mci; + int started; + int t2_signalling_valid; + int iq_constellation_point; + int iq_constellation_point_max; + int iq_constellation_tap; + int first_time_lock; }; +static int stop(struct dvb_frontend *fe) +{ + struct m4 *state = fe->demodulator_priv; + struct mci_command cmd; + struct mci_base *mci_base = state->mci.base; + + if (!state->started) + return -1; + state->started = 0; + state->t2_signalling_valid = 0; + memset(&cmd, 0, sizeof(cmd)); + cmd.command = MCI_CMD_STOP; + cmd.demod = state->mci.demod; + ddb_mci_cmd(&state->mci, &cmd, NULL); + return 0; +} + +static int search_s2(struct dvb_frontend *fe) +{ + struct m4 *state = fe->demodulator_priv; + struct mci_base *mci_base = state->mci.base; + struct m4_base *m4_base = (struct m4_base *) mci_base; + struct dtv_frontend_properties *p = &fe->dtv_property_cache; + struct mci_command cmd; + int stat; + + memset(&cmd, 0, sizeof(cmd)); + cmd.command = MCI_CMD_SEARCH_DVBS; + cmd.dvbs2_search.flags = 3; + cmd.dvbs2_search.s2_modulation_mask = 3; + cmd.dvbs2_search.retry = 2; + cmd.dvbs2_search.frequency = p->frequency * 1000; + cmd.dvbs2_search.symbol_rate = p->symbol_rate; + cmd.dvbs2_search.scrambling_sequence_index = 0; //p->scrambling_sequence_index; + cmd.dvbs2_search.input_stream_id = p->stream_id; + cmd.tuner = state->mci.nr; + cmd.demod = state->mci.tuner; + cmd.output = state->mci.nr; + + stat = ddb_mci_cmd(&state->mci, &cmd, NULL); + if (stat) + stop(fe); + return stat; +} + +static int search_c(struct dvb_frontend *fe) +{ + struct m4 *state = fe->demodulator_priv; + struct mci_base *mci_base = state->mci.base; + struct m4_base *m4_base = (struct m4_base *) mci_base; + struct dtv_frontend_properties *p = &fe->dtv_property_cache; + struct mci_command cmd; + int stat; + + memset(&cmd, 0, sizeof(cmd)); + cmd.command = MCI_CMD_SEARCH_DVBC; + switch (p->bandwidth_hz) { + case 6000000: + cmd.dvbc_search.bandwidth = MCI_BANDWIDTH_6MHZ; + break; + case 7000000: + cmd.dvbc_search.bandwidth = MCI_BANDWIDTH_7MHZ; + break; + default: + cmd.dvbc_search.bandwidth = MCI_BANDWIDTH_8MHZ; + break; + } + cmd.dvbc_search.retry = 2; + cmd.dvbc_search.frequency = p->frequency; + cmd.tuner = state->mci.tuner; + cmd.demod = state->mci.demod; + cmd.output = state->mci.nr; + + stat = ddb_mci_cmd(&state->mci, &cmd, NULL); + if (stat) + stop(fe); + return stat; +} + +static int search_t(struct dvb_frontend *fe) +{ + struct m4 *state = fe->demodulator_priv; + struct mci_base *mci_base = state->mci.base; + struct m4_base *m4_base = (struct m4_base *) mci_base; + struct dtv_frontend_properties *p = &fe->dtv_property_cache; + struct mci_command cmd; + int stat; + + memset(&cmd, 0, sizeof(cmd)); + cmd.command = MCI_CMD_SEARCH_DVBT; + switch (p->bandwidth_hz) { + case 5000000: + cmd.dvbt_search.bandwidth = MCI_BANDWIDTH_5MHZ; + break; + case 6000000: + cmd.dvbt_search.bandwidth = MCI_BANDWIDTH_6MHZ; + break; + case 7000000: + cmd.dvbt_search.bandwidth = MCI_BANDWIDTH_7MHZ; + break; + default: + cmd.dvbt_search.bandwidth = MCI_BANDWIDTH_8MHZ; + break; + } + cmd.dvbt_search.retry = 2; + cmd.dvbt_search.frequency = p->frequency; + cmd.tuner = state->mci.tuner; + cmd.demod = state->mci.demod; + cmd.output = state->mci.nr; + + stat = ddb_mci_cmd(&state->mci, &cmd, NULL); + if (stat) + stop(fe); + return stat; +} + +static int search_t2(struct dvb_frontend *fe) +{ + struct m4 *state = fe->demodulator_priv; + struct mci_base *mci_base = state->mci.base; + struct m4_base *m4_base = (struct m4_base *) mci_base; + struct dtv_frontend_properties *p = &fe->dtv_property_cache; + struct mci_command cmd; + int stat; + u32 flags = 0; + + memset(&cmd, 0, sizeof(cmd)); + cmd.command = MCI_CMD_SEARCH_DVBT2; + switch (p->bandwidth_hz) { + case 1700000: + cmd.dvbt_search.bandwidth = MCI_BANDWIDTH_1_7MHZ; + break; + case 5000000: + cmd.dvbt_search.bandwidth = MCI_BANDWIDTH_5MHZ; + break; + case 6000000: + cmd.dvbt_search.bandwidth = MCI_BANDWIDTH_6MHZ; + break; + case 7000000: + cmd.dvbt_search.bandwidth = MCI_BANDWIDTH_7MHZ; + break; + default: + cmd.dvbt_search.bandwidth = MCI_BANDWIDTH_8MHZ; + break; + } + cmd.dvbt2_search.retry = 2; + cmd.dvbt2_search.frequency = p->frequency; + if (p->stream_id != NO_STREAM_ID_FILTER) { + cmd.dvbt2_search.plp = p->stream_id & 0xff; + cmd.dvbt2_search.flags |= 0x80; + cmd.dvbt2_search.flags |= (p->stream_id >> 8) & 1; + } + cmd.tuner = state->mci.tuner; + cmd.demod = state->mci.demod; + cmd.output = state->mci.nr; + + stat = ddb_mci_cmd(&state->mci, &cmd, NULL); + if (stat) + stop(fe); + return stat; +} + +static int search_c2(struct dvb_frontend *fe) +{ + struct m4 *state = fe->demodulator_priv; + struct mci_base *mci_base = state->mci.base; + struct m4_base *m4_base = (struct m4_base *) mci_base; + struct dtv_frontend_properties *p = &fe->dtv_property_cache; + struct mci_command cmd; + int stat; + u32 flags = 0; + + memset(&cmd, 0, sizeof(cmd)); + cmd.command = MCI_CMD_SEARCH_DVBC2; + switch (p->bandwidth_hz) { + case 6000000: + cmd.dvbc2_search.bandwidth = MCI_BANDWIDTH_6MHZ; + break; + default: + cmd.dvbc2_search.bandwidth = MCI_BANDWIDTH_8MHZ; + break; + } + cmd.dvbc2_search.retry = 2; + cmd.dvbc2_search.frequency = p->frequency; + if (p->stream_id != NO_STREAM_ID_FILTER) { + cmd.dvbc2_search.plp = p->stream_id & 0xff; + cmd.dvbc2_search.data_slice = (p->stream_id >> 8) & 0xff; + } + cmd.tuner = state->mci.tuner; + cmd.demod = state->mci.demod; + cmd.output = state->mci.nr; + + stat = ddb_mci_cmd(&state->mci, &cmd, NULL); + if (stat) + stop(fe); + return stat; +} + +static int search_isdbt(struct dvb_frontend *fe) +{ + struct m4 *state = fe->demodulator_priv; + struct mci_base *mci_base = state->mci.base; + struct m4_base *m4_base = (struct m4_base *) mci_base; + struct dtv_frontend_properties *p = &fe->dtv_property_cache; + struct mci_command cmd; + int stat; + u32 flags = 0; + + memset(&cmd, 0, sizeof(cmd)); + cmd.command = MCI_CMD_SEARCH_ISDBT; + switch (p->bandwidth_hz) { + case 8000000: + cmd.isdbt_search.bandwidth = MCI_BANDWIDTH_8MHZ; + break; + case 7000000: + cmd.isdbt_search.bandwidth = MCI_BANDWIDTH_7MHZ; + break; + default: + cmd.isdbt_search.bandwidth = MCI_BANDWIDTH_6MHZ; + break; + } + cmd.isdbt_search.retry = 2; + cmd.isdbt_search.frequency = p->frequency; + cmd.tuner = state->mci.tuner; + cmd.demod = state->mci.demod; + cmd.output = state->mci.nr; + + stat = ddb_mci_cmd(&state->mci, &cmd, NULL); + if (stat) + stop(fe); + return stat; +} + + +static int set_parameters(struct dvb_frontend *fe) +{ + struct m4 *state = fe->demodulator_priv; + int res; + + stop(fe); + + state->t2_signalling_valid = 0; + state->iq_constellation_point = 0; + state->iq_constellation_point_max = 0; + + state->iq_constellation_tap = 0; + switch (fe->dtv_property_cache.delivery_system) { + case SYS_DVBS: + case SYS_DVBS2: + res = search_s2(fe); + break; + case SYS_DVBC_ANNEX_A: + res = search_c(fe); + break; + case SYS_DVBT: + state->iq_constellation_tap = 5; + res = search_t(fe); + break; + case SYS_DVBT2: + res = search_t2(fe); + break; + case SYS_DVBC2: + res = search_c2(fe); + break; + case SYS_ISDBT: + res = search_isdbt(fe); + break; + default: + return -EINVAL; + } + if (!res) { + state->started = 1; + state->first_time_lock = 1; + } + return res; +} + +static int read_status(struct dvb_frontend *fe, enum fe_status *status) +{ + int stat; + struct m4 *state = fe->demodulator_priv; + struct mci_result res; + + stat = ddb_mci_get_status(&state->mci, &res); + if (stat) + return stat; + *status = 0x00; + ddb_mci_get_info(&state->mci); + ddb_mci_get_strength(fe); + if (res.status == M4_DEMOD_WAIT_SIGNAL) + *status = 0x01; + if (res.status == M4_DEMOD_LOCKED) { + *status = 0x1f; + ddb_mci_get_snr(fe); + } + return stat; +} + +static int tune(struct dvb_frontend *fe, bool re_tune, + unsigned int mode_flags, + unsigned int *delay, enum fe_status *status) +{ + int r; + + if (re_tune) { + r = set_parameters(fe); + if (r) + return r; + } + r = read_status(fe, status); + if (r) + return r; + + if (*status & FE_HAS_LOCK) + return 0; + *delay = HZ / 10; + return 0; +} + +static int sleep(struct dvb_frontend *fe) +{ + struct m4 *state = fe->demodulator_priv; + + if (state->started) + stop(fe); + return 0; +} + +static void release(struct dvb_frontend *fe) +{ + struct m4 *state = fe->demodulator_priv; + struct mci_base *mci_base = state->mci.base; + + mci_base->count--; + if (mci_base->count == 0) { + list_del(&mci_base->mci_list); + kfree(mci_base); + } + kfree(state); +} + +static int get_algo(struct dvb_frontend *fe) +{ + return DVBFE_ALGO_HW; +} + static struct dvb_frontend_ops m4_ops = { .delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT, SYS_DVBT2, SYS_DVBC2, SYS_ISDBT, SYS_DVBS, SYS_DVBS2, }, .info = { .name = "M4", - .frequency_min = 47000000, /* DVB-T: 47125000 */ + .frequency_min = 950000, /* DVB-T: 47125000 */ .frequency_max = 865000000, /* DVB-C: 862000000 */ - .symbol_rate_min = 870000, - .symbol_rate_max = 11700000, + .symbol_rate_min = 100000, + .symbol_rate_max = 100000000, .frequency_stepsize = 0, .frequency_tolerance = 0, .caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 | @@ -57,14 +409,11 @@ static struct dvb_frontend_ops m4_ops = { FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION }, -#if 0 - .get_frontend_algo = get_algo, - .tune = tune, .release = release, + .get_frontend_algo = get_algo, .read_status = read_status, - .set_input = set_input, + .tune = tune, .sleep = sleep, -#endif }; static int init(struct mci *mci) diff --git a/ddbridge/ddbridge-max.c b/ddbridge/ddbridge-max.c index 155252a..2effee7 100644 --- a/ddbridge/ddbridge-max.c +++ b/ddbridge/ddbridge-max.c @@ -60,6 +60,24 @@ static int lnb_command(struct ddb *dev, u32 link, u32 lnb, u32 cmd) return 0; } +static int max_set_input_unlocked(struct dvb_frontend *fe, int in); + +static int max_emulate_switch(struct dvb_frontend *fe, + u8 *cmd, u32 len) +{ + int input; + + if (len !=4) + return -1; + + if ((cmd[0] != 0xe0) || (cmd[1] != 0x10) || (cmd[2] != 0x39)) + return -1; + + input = cmd[3] & 3; + max_set_input_unlocked(fe, input); + return 0; +} + static int max_send_master_cmd(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd) { @@ -73,6 +91,10 @@ static int max_send_master_cmd(struct dvb_frontend *fe, if (fmode == 2 || fmode == 1) return 0; + + if (fmode == 4) + max_emulate_switch(fe, cmd->msg, cmd->msg_len); + if (dvb->diseqc_send_master_cmd) dvb->diseqc_send_master_cmd(fe, cmd); @@ -181,7 +203,8 @@ static int max_set_input_unlocked(struct dvb_frontend *fe, int in) dvb->input = in; dev->link[port->lnr].lnb.voltage[dvb->input] |= obit; } - res = dvb->set_input(fe, in); + if (dvb->set_input) + res = dvb->set_input(fe, in); return res; } @@ -416,7 +439,7 @@ int ddb_fe_attach_mxl5xx(struct ddb_input *input) demod = input->nr; tuner = demod & 3; - if (fmode == 3) + if (fmode >= 3) tuner = 0; dvb->fe = dvb_attach(mxl5xx_attach, i2c, &cfg, demod, tuner); if (!dvb->fe) { @@ -456,16 +479,18 @@ int ddb_fe_attach_mci(struct ddb_input *input, u32 type) struct ddb_link *link = &dev->link[port->lnr]; int demod, tuner; struct mci_cfg cfg; - + int fm = fmode; + demod = input->nr; tuner = demod & 3; switch (type) { case DDB_TUNER_MCI_SX8: cfg = ddb_max_sx8_cfg; - if (fmode == 3) + if (fm >= 3) tuner = 0; break; case DDB_TUNER_MCI_M4: + fm = 0; cfg = ddb_max_m4_cfg; break; default: @@ -480,7 +505,7 @@ int ddb_fe_attach_mci(struct ddb_input *input, u32 type) lnb_command(dev, port->lnr, input->nr, LNB_CMD_INIT); lnb_set_voltage(dev, port->lnr, input->nr, SEC_VOLTAGE_OFF); } - ddb_lnb_init_fmode(dev, link, fmode); + ddb_lnb_init_fmode(dev, link, fm); dvb->fe->ops.set_voltage = max_set_voltage; dvb->fe->ops.enable_high_lnb_voltage = max_enable_high_lnb_voltage; @@ -494,4 +519,3 @@ int ddb_fe_attach_mci(struct ddb_input *input, u32 type) dvb->input = tuner; return 0; } - diff --git a/ddbridge/ddbridge-mci.c b/ddbridge/ddbridge-mci.c index e170556..107c776 100644 --- a/ddbridge/ddbridge-mci.c +++ b/ddbridge/ddbridge-mci.c @@ -149,6 +149,52 @@ static int ddb_mci_get_iq(struct mci *mci, u32 demod, s16 *i, s16 *q) return stat; } +int ddb_mci_get_status(struct mci *mci, struct mci_result *res) +{ + struct mci_command cmd; + + cmd.command = MCI_CMD_GETSTATUS; + cmd.demod = mci->demod; + return ddb_mci_cmd_raw(mci, &cmd, 1, res, 1); +} + +int ddb_mci_get_snr(struct dvb_frontend *fe) +{ + struct mci *mci = fe->demodulator_priv; + struct dtv_frontend_properties *p = &fe->dtv_property_cache; + + p->cnr.len = 1; + p->cnr.stat[0].scale = FE_SCALE_DECIBEL; + p->cnr.stat[0].svalue = (s64) mci-> + signal_info.dvbs2_signal_info.signal_to_noise * 10; + return 0; +} + +int ddb_mci_get_strength(struct dvb_frontend *fe) +{ + struct mci *mci = fe->demodulator_priv; + struct dtv_frontend_properties *p = &fe->dtv_property_cache; + s32 str; + + str = mci->signal_info.dvbs2_signal_info.channel_power * 10; + p->strength.len = 1; + p->strength.stat[0].scale = FE_SCALE_DECIBEL; + p->strength.stat[0].svalue = str; + return 0; +} + +int ddb_mci_get_info(struct mci *mci) +{ + int stat; + struct mci_command cmd; + + memset(&cmd, 0, sizeof(cmd)); + cmd.command = MCI_CMD_GETSIGNALINFO; + cmd.demod = mci->demod; + stat = ddb_mci_cmd(mci, &cmd, &mci->signal_info); + return stat; +} + static void mci_handler(void *priv) { struct mci_base *base = (struct mci_base *)priv; diff --git a/ddbridge/ddbridge-mci.h b/ddbridge/ddbridge-mci.h index 52a0049..7c9e3c6 100644 --- a/ddbridge/ddbridge-mci.h +++ b/ddbridge/ddbridge-mci.h @@ -97,8 +97,6 @@ #define SX8_DEMOD_IQ_MODE (1) #define SX8_DEMOD_WAIT_SIGNAL (2) #define SX8_DEMOD_WAIT_MATYPE (3) -#define SX8_DEMOD_WAIT_FEC (4) -#define SX8_DEMOD_WAIT_FEC_S1 (5) #define SX8_DEMOD_TIMEOUT (14) #define SX8_DEMOD_LOCKED (15) @@ -116,19 +114,24 @@ #define MCI_CMD_SEARCH_DVBC (0x20) #define MCI_CMD_SEARCH_DVBT (0x21) #define MCI_CMD_SEARCH_DVBT2 (0x22) +#define MCI_CMD_SEARCH_DVBC2 (0x23) +#define MCI_CMD_SEARCH_ISDBT (0x24) #define MCI_CMD_GET_IQSYMBOL (0x30) -#define MCI_BANDWIDTH_1_7MHZ (0) -#define MCI_BANDWIDTH_5MHZ (1) -#define MCI_BANDWIDTH_6MHZ (2) -#define MCI_BANDWIDTH_7MHZ (3) -#define MCI_BANDWIDTH_8MHZ (4) +#define MCI_BANDWIDTH_UNKNOWN (0) +#define MCI_BANDWIDTH_1_7MHZ (1) +#define MCI_BANDWIDTH_5MHZ (5) +#define MCI_BANDWIDTH_6MHZ (6) +#define MCI_BANDWIDTH_7MHZ (7) +#define MCI_BANDWIDTH_8MHZ (8) -#define M4_MODE_SX (2) -#define M4_MODE_C (3) -#define M4_MODE_T (4) -#define M4_MODE_T2 (5) +#define M4_MODE_DVBSX (2) +#define M4_MODE_DVBC (3) +#define M4_MODE_DVBT (4) +#define M4_MODE_DVBT2 (5) +#define M4_MODE_DVBC2 (6) +#define M4_MODE_ISDBT (7) #define SX8_CMD_INPUT_ENABLE (0x40) #define SX8_CMD_INPUT_DISABLE (0x41) @@ -138,6 +141,8 @@ #define SX8_CMD_DISABLE_IQOUTPUT (0x45) #define M4_CMD_GET_T2_L1INFO (0x50) +#define M4_CMD_GET_C2_L1P2 (0x50) +#define M4_CMD_GET_IDS (0x51) #define MCI_STATUS_OK (0x00) #define MCI_STATUS_UNSUPPORTED (0x80) @@ -175,52 +180,85 @@ struct mci_command { u32 scrambling_sequence_index; u32 frequency_range; } dvbs2_search; + struct { - uint8_t flags; - uint8_t bandwidth; - uint8_t rsvd1; - uint8_t retry; - uint32_t frequency; + u8 flags; + u8 bandwidth; + u8 rsvd1; + u8 retry; + u32 frequency; } dvbc_search; struct { - uint8_t flags; /* Bit 0: LP Stream */ - uint8_t bandwidth; - uint8_t rsvd1; - uint8_t retry; - uint32_t frequency; + u8 flags; /* Bit 0: LP Stream */ + u8 bandwidth; + u8 rsvd1; + u8 retry; + u32 frequency; } dvbt_search; struct { - uint8_t flags; /* Bit 0: T2 Lite Profile, 7: PLP, */ - uint8_t bandwidth; - uint8_t rsvd1; - uint8_t retry; - uint32_t frequency; - uint32_t reserved; - uint8_t plp; - uint8_t rsvd2[3]; + u8 flags; /* Bit 0: T2 Lite Profile, 7: PLP, */ + u8 bandwidth; + u8 rsvd1; + u8 retry; + u32 frequency; + u32 reserved; + u8 plp; + u8 rsvd2[3]; } dvbt2_search; struct { - uint8_t Tap; - uint8_t Rsvd; - uint16_t Point; + u8 flags; + u8 bandwidth; + u8 rsvd1; + u8 retry; + u32 frequency; + u32 reserved; + u8 plp; + u8 data_slice; + u8 rsvd2[2]; + } dvbc2_search; + + struct { + u8 flags; + u8 bandwidth; + u8 rsvd1; + u8 retry; + u32 frequency; + } isdbt_search; + + struct { + u8 tap; + u8 rsvd; + u16 point; } get_iq_symbol; struct { - uint8_t flags; /* Bit 0 : 0 = VTM, 1 = SCAN. Bit 1: Set Gain */ - uint8_t roll_off; - uint8_t rsvd1; - uint8_t rsvd2; - uint32_t frequency; - uint32_t symbol_rate; /* Only in VTM mode. */ - uint16_t gain; + u8 flags; /* Bit 0 : 0 = VTM, 1 = SCAN. Bit 1: Set Gain */ + u8 roll_off; + u8 rsvd1; + u8 rsvd2; + u32 frequency; + u32 symbol_rate; /* Only in VTM mode. */ + u16 gain; } sx8_start_iq; struct { - uint8_t flags; /* Bit 1:0 = STVVGLNA Gain. 0 = AGC, 1 = 0dB, 2 = Minimum, 3 = Maximum */ + u8 flags; /* Bit 1:0 = STVVGLNA Gain. 0 = AGC, 1 = 0dB, 2 = Minimum, 3 = Maximum */ } sx8_input_enable; + + struct { + u8 Offset; // Offset into list, must be multiple of 64 + u8 Select; // 0 = Slices, 1 = PLPs (C2 Only) + u8 DataSlice; // DataSlice to get PLPList (C2 Only) + } Get_IDs; + + struct { + u8 Select; // 0 = Base, 1 = DataSilce, 2 = PLP, Bit 7: Set new ID + u8 ID; // DataSliceID, PLPId + } Get_L1Info; + }; }; @@ -250,6 +288,7 @@ struct mci_result { u32 ber_numerator; /* Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X */ u32 ber_denominator; } dvbs2_signal_info; + struct { u8 modulation; u8 rsvd1[3]; @@ -260,9 +299,10 @@ struct mci_result { s16 signal_to_noise; /* SNR in dB x 100, Note: negativ values are valid in DVB-S2 */ s16 rsvd2; u32 packet_errors; /* Counter for packet errors. (set to 0 on Start command) */ - u32 ber_numerator; /* Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X */ + u32 ber_numerator; /* Bit error rate: PreRS */ u32 ber_denominator; } dvbc_signal_info; + struct { u8 tps_25_32; /* Constellation (2), Hierarchy (3), Coderate HP (3) */ u8 tps_33_39; /* Coderate LP (3), Guardinterval (2), FFT (2), 0 (1) */ @@ -274,9 +314,10 @@ struct mci_result { s16 signal_to_noise; /* SNR in dB x 100, Note: negativ values are valid in DVB-S2 */ s16 rsvd2; u32 packet_errors; /* Counter for packet errors. (set to 0 on Start command) */ - u32 ber_numerator; /* Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X */ + u32 ber_numerator; /* Bit error rate: PreRS */ u32 ber_denominator; } dvbt_signal_info; + struct { u32 rsvd0; u32 frequency; /* actual frequency in Hz */ @@ -286,9 +327,40 @@ struct mci_result { s16 signal_to_noise; /* SNR in dB x 100, Note: negativ values are valid in DVB-S2 */ s16 rsvd2; u32 packet_errors; /* Counter for packet errors. (set to 0 on Start command) */ - u32 ber_numerator; /* Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X */ + u32 ber_numerator; /* Bit error rate: PreRS */ u32 ber_denominator; } dvbt2_signal_info; + + struct { // Work in Progress + u32 rsvd0 ; // Cell Identifier + + u32 frequency; // actual frequency in Hz + u32 rsvd1; // + s16 channel_power; // channel power in dBm x 100 + s16 band_power; // band power in dBm x 100 + s16 signal_to_noise; // SNR in dB x 100, Note: negativ values are valid in DVB-S2 + s16 rsvd2; + u32 packet_errors; // Counter for packet errors. (set to 0 on Start command) + u32 ber_numerator; // Bit error rate: PreBCH + u32 ber_denominator; + } DVBC2_SignalInfo; + + struct { + u32 rsvd0; + + u32 frequency; // actual frequency in Hz + u32 rsvd1; // + s16 channel_power; // channel power in dBm x 100 + s16 band_power; // band power in dBm x 100 + s16 signal_to_noise; // SNR in dB x 100, Note: negativ values are valid in DVB-S2 + s16 rsvd2; + u32 packet_errors; // Counter for packet errors. (set to 0 on Start command) + u32 ber_numerator; // Bit error rate: PreRS + u32 ber_denominator; + + u8 tmcc_info[13]; // TMCC B20 - B121 + } isdbt_signal_info; + struct { s16 i; s16 q; @@ -299,6 +371,61 @@ struct mci_result { u8 t2_l1_post_d[19]; u8 t2_l1_post_c[19]; } dvbt2_l1_info; + + struct { + u8 NetworkID[2]; + u8 C2SystemID[2]; + u8 StartFrequency[3]; + u8 C2BandWidth[2]; + u8 GuardInterval; + u8 C2FrameLength[2]; + u8 L1P2ChangeCounter; + u8 NumDataSlices; + u8 NumNotches; + struct { + u8 Start[2]; + u8 Width[2]; + u8 Reserved3; + } NotchData[15]; + u8 ReservedTone; + u8 Reserved4[2]; // EWS 1 bit, C2_Version 4 bit, Rsvd 11 bit + } DVBC2_L1Part2; + + struct { + u8 NumIDs; + u8 Offset; + u8 IDs[64]; + } DVBC2_IDList; + + struct { + u8 SliceID; + u8 TunePosition[2]; + u8 OffsetLeft[2]; + u8 OffsetRight[2]; + u8 TIDepth; + u8 Type; + u8 FECHeaderType; + u8 ConstConf; + u8 LeftNotch; + u8 NumPLP; + u8 Reserved2; + } DVBC2_SliceInfo; + + struct { + u8 PLPID; + u8 Bundled; + u8 Type; + u8 PayloadType; + u8 GroupID; + u8 Start[2]; + u8 FEC_Type; + u8 Mod; + u8 Cod; + u8 PSISIReprocessing; + u8 TransportstreamID[2]; + u8 OrginalNetworkID[2]; + u8 Reserved1; + } DVBC2_PLPInfo; }; u32 version[4]; }; @@ -391,11 +518,26 @@ struct mci { int nr; int demod; int tuner; + + struct mci_result signal_info; +}; + +struct mci_cfg { + int type; + struct dvb_frontend_ops *fe_ops; + u32 base_size; + u32 state_size; + int (*init)(struct mci *mci); + int (*base_init)(struct mci_base *mci_base); }; int ddb_mci_cmd(struct mci *state, struct mci_command *command, struct mci_result *result); int ddb_mci_cmd_raw(struct mci *state, struct mci_command *command, u32 command_len, struct mci_result *result, u32 result_len); int ddb_mci_config(struct mci *state, u32 config); +int ddb_mci_get_status(struct mci *mci, struct mci_result *res); +int ddb_mci_get_snr(struct dvb_frontend *fe); +int ddb_mci_get_info(struct mci *mci); +int ddb_mci_get_strength(struct dvb_frontend *fe); #endif diff --git a/ddbridge/ddbridge-sx8.c b/ddbridge/ddbridge-sx8.c index ecee7da..4bd24e6 100644 --- a/ddbridge/ddbridge-sx8.c +++ b/ddbridge/ddbridge-sx8.c @@ -52,7 +52,6 @@ struct sx8 { int first_time_lock; int started; - struct mci_result signal_info; u32 bb_mode; u32 local_frequency; @@ -108,64 +107,23 @@ static void release(struct dvb_frontend *fe) kfree(state); } -static int get_info(struct dvb_frontend *fe) -{ - int stat; - struct sx8 *state = fe->demodulator_priv; - struct mci_command cmd; - - memset(&cmd, 0, sizeof(cmd)); - cmd.command = MCI_CMD_GETSIGNALINFO; - cmd.demod = state->mci.demod; - stat = ddb_mci_cmd(&state->mci, &cmd, &state->signal_info); - return stat; -} - -static int get_snr(struct dvb_frontend *fe) -{ - struct sx8 *state = fe->demodulator_priv; - struct dtv_frontend_properties *p = &fe->dtv_property_cache; - - p->cnr.len = 1; - p->cnr.stat[0].scale = FE_SCALE_DECIBEL; - p->cnr.stat[0].svalue = (s64) state->signal_info.dvbs2_signal_info.signal_to_noise * 10; - return 0; -} - -static int get_strength(struct dvb_frontend *fe) -{ - struct sx8 *state = fe->demodulator_priv; - struct dtv_frontend_properties *p = &fe->dtv_property_cache; - s32 str; - - str = state->signal_info.dvbs2_signal_info.channel_power * 10; - p->strength.len = 1; - p->strength.stat[0].scale = FE_SCALE_DECIBEL; - p->strength.stat[0].svalue = str; - return 0; -} - static int read_status(struct dvb_frontend *fe, enum fe_status *status) { int stat; struct sx8 *state = fe->demodulator_priv; - struct mci_command cmd; - u32 val; - struct mci_result *res = (struct mci_result *)&val; + struct mci_result res; - cmd.command = MCI_CMD_GETSTATUS; - cmd.demod = state->mci.demod; - stat = ddb_mci_cmd_raw(&state->mci, &cmd, 1, res, 1); + stat = ddb_mci_get_status(&state->mci, &res); if (stat) return stat; *status = 0x00; - get_info(fe); - get_strength(fe); - if (res->status == SX8_DEMOD_WAIT_MATYPE) + ddb_mci_get_info(&state->mci); + ddb_mci_get_strength(fe); + if (res.status == SX8_DEMOD_WAIT_MATYPE) *status = 0x0f; - if (res->status == SX8_DEMOD_LOCKED) { + if (res.status == SX8_DEMOD_LOCKED) { *status = 0x1f; - get_snr(fe); + ddb_mci_get_snr(fe); } return stat; } @@ -346,7 +304,8 @@ unlock: } -static int start_iq(struct dvb_frontend *fe, u32 flags, u32 roll_off, u32 ts_config) +static int start_iq(struct dvb_frontend *fe, u32 flags, + u32 roll_off, u32 ts_config) { struct sx8 *state = fe->demodulator_priv; struct mci_base *mci_base = state->mci.base; @@ -408,7 +367,7 @@ static int set_parameters(struct dvb_frontend *fe) } if (iq_mode) ts_config = (SX8_TSCONFIG_TSHEADER | SX8_TSCONFIG_MODE_IQ); - if (iq_mode < 3) { + if (iq_mode < 2) { u32 mask; switch (p->modulation) { @@ -433,14 +392,12 @@ static int set_parameters(struct dvb_frontend *fe) } stat = start(fe, 3, mask, ts_config); } else { - u32 flags = (iq_mode == 2) ? 1 : 0; - - stat = start_iq(fe, flags, 4, ts_config); + stat = start_iq(fe, iq_mode & 1, 4, ts_config); } if (!stat) { state->started = 1; state->first_time_lock = 1; - state->signal_info.status = SX8_DEMOD_WAIT_SIGNAL; + state->mci.signal_info.status = SX8_DEMOD_WAIT_SIGNAL; } return stat; } @@ -489,8 +446,6 @@ static int set_input(struct dvb_frontend *fe, int input) static int sleep(struct dvb_frontend *fe) { - struct sx8 *state = fe->demodulator_priv; - stop(fe); return 0; } diff --git a/ddbridge/ddbridge.h b/ddbridge/ddbridge.h index c9b42e9..a772fee 100644 --- a/ddbridge/ddbridge.h +++ b/ddbridge/ddbridge.h @@ -567,15 +567,6 @@ int ddb_lnb_init_fmode(struct ddb *dev, struct ddb_link *link, u32 fm); struct ddb_irq *ddb_irq_set(struct ddb *dev, u32 link, u32 nr, void (*handler)(void *), void *data); -struct mci_cfg { - int type; - struct dvb_frontend_ops *fe_ops; - u32 base_size; - u32 state_size; - int (*init)(struct mci *mci); - int (*base_init)(struct mci_base *mci_base); -}; - struct dvb_frontend *ddb_mci_attach(struct ddb_input *input, struct mci_cfg *cfg, int nr, int tuner); #endif