--- v4l-dvb/linux/drivers/media/dvb/frontends/mt312.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/mt312.c 2006-07-23 11:39:03.000000000 +0400 @@ -208,7 +208,7 @@ static int mt312_get_symbol_rate(struct return 0; } -static int mt312_get_code_rate(struct mt312_state* state, fe_code_rate_t *cr) +static int mt312_get_code_rate_compat(struct mt312_state* state, fe_code_rate_t *cr) { const fe_code_rate_t fec_tab[8] = { FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_6_7, FEC_7_8, @@ -225,6 +225,30 @@ static int mt312_get_code_rate(struct mt return 0; } +static int mt312_get_code_rate(struct mt312_state* state, enum dvbfe_fec *cr) +{ + enum dvbfe_fec fec_tab[8] = { + DVBFE_FEC_1_2, + DVBFE_FEC_2_3, + DVBFE_FEC_3_4, + DVBFE_FEC_5_6, + DVBFE_FEC_6_7, + DVBFE_FEC_7_8, + DVBFE_FEC_AUTO, + DVBFE_FEC_AUTO + }; + + int ret; + u8 fec_status; + + if ((ret = mt312_readreg(state, FEC_STATUS, &fec_status)) < 0) + return ret; + + *cr = fec_tab[(fec_status >> 4) & 0x07]; + + return 0; +} + static int mt312_initfe(struct dvb_frontend* fe) { struct mt312_state *state = fe->demodulator_priv; @@ -522,9 +546,10 @@ static int mt312_set_frontend(struct dvb return -EINVAL; } - if (fe->ops.tuner_ops.set_params) { - fe->ops.tuner_ops.set_params(fe, p); - if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + if (fe->ops.tuner_ops.set_params_compat) { + fe->ops.tuner_ops.set_params_compat(fe, p); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); } /* sr = (u16)(sr * 256.0 / 1000000.0) */ @@ -566,7 +591,7 @@ static int mt312_get_frontend(struct dvb if ((ret = mt312_get_symbol_rate(state, &p->u.qpsk.symbol_rate)) < 0) return ret; - if ((ret = mt312_get_code_rate(state, &p->u.qpsk.fec_inner)) < 0) + if ((ret = mt312_get_code_rate_compat(state, &p->u.qpsk.fec_inner)) < 0) return ret; return 0; @@ -617,6 +642,200 @@ static void mt312_release(struct dvb_fro kfree(state); } +static struct dvbfe_info vp310_info = { + .name = "Zarlink VP310 DVB-S", + .delivery = DVBFE_DELSYS_DVBS, + .delsys = { + .dvbs.modulation = DVBFE_MOD_QPSK, + .dvbs.fec = DVBFE_FEC_1_2 | DVBFE_FEC_2_3 | + DVBFE_FEC_3_4 | DVBFE_FEC_5_6 | + DVBFE_FEC_7_8 | DVBFE_FEC_AUTO + }, + + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_step = (MT312_PLL_CLK / 1000) / 128, + .symbol_rate_min = MT312_SYS_CLK / 128, + .symbol_rate_max = MT312_SYS_CLK / 2 +}; + +static struct dvbfe_info mt312_info = { + .name = "Zarlink MT312 DVB-S", + .delivery = DVBFE_DELSYS_DVBS, + .delsys = { + .dvbs.modulation = DVBFE_MOD_QPSK, + .dvbs.fec = DVBFE_FEC_1_2 | DVBFE_FEC_2_3 | + DVBFE_FEC_3_4 | DVBFE_FEC_5_6 | + DVBFE_FEC_7_8 | DVBFE_FEC_AUTO + }, + + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_step = (MT312_PLL_CLK / 1000) / 128, + .symbol_rate_min = MT312_SYS_CLK / 128, + .symbol_rate_max = MT312_SYS_CLK / 2 +}; + +static int mt312_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info) +{ + struct mt312_state *state = fe->demodulator_priv; + + switch (state->id) { + case ID_VP310: + memcpy(fe_info, &vp310_info, sizeof (vp310_info)); + break; + case ID_MT312: + memcpy(fe_info, &mt312_info, sizeof (mt312_info)); + break; + default: + break; + } + + return 0; +} + +static int mt312_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_DVBS; + + return 0; +} + +static int mt312_set_params(struct dvb_frontend* fe, + struct dvbfe_params *p) +{ + struct mt312_state *state = fe->demodulator_priv; + int ret; + u8 buf[5], config_val; + u16 sr; + + const u8 fec_tab[15] = { + 0x00, // NONE + 0x00, // 1_4 + 0x00, // 1_3 + 0x00, // 2_5 + 0x01, // 1_2 + 0x00, // 3_5 + 0x02, // 2_3 + 0x04, // 3_4 + 0x3f, // 4_5 + 0x08, // 5_6 + 0x10, // 6_7 + 0x20, // 7_8 + 0x3f, // 8_9 + 0x00, // 9_10 + 0x3f // AUTO + }; + + const u8 inv_tab[3] = { 0x00, 0x40, 0x80 }; + + dprintk("%s: Freq %d\n", __FUNCTION__, p->frequency); + +// if ((p->frequency < fe->ops.info.frequency_min) || +// (p->frequency > fe->ops.info.frequency_max)) +// return -EINVAL; + +// if ((p->inversion < INVERSION_OFF) || +// (p->inversion > INVERSION_ON)) +// return -EINVAL; + +// if ((p->u.qpsk.symbol_rate < fe->ops.info.symbol_rate_min) || +// (p->u.qpsk.symbol_rate > fe->ops.info.symbol_rate_max)) +// return -EINVAL; + +// if ((p->u.qpsk.fec_inner < FEC_NONE) || +// (p->u.qpsk.fec_inner > FEC_AUTO)) +// return -EINVAL; + +// if ((p->u.qpsk.fec_inner == FEC_4_5) || +// (p->u.qpsk.fec_inner == FEC_8_9)) +// return -EINVAL; + + switch (state->id) { + case ID_VP310: + // For now we will do this only for the VP310. + // It should be better for the mt312 as well, but tunning will be slower. ACCJr 09/29/03 + ret = mt312_readreg(state, CONFIG, &config_val); + if (ret < 0) + return ret; + if (p->delsys.dvbs.symbol_rate >= 30000000) { //Note that 30MS/s should use 90MHz + if ((config_val & 0x0c) == 0x08) { //We are running 60MHz + state->frequency = 90; + if ((ret = mt312_initfe(fe)) < 0) + return ret; + } + } else { + if ((config_val & 0x0c) == 0x0C) { //We are running 90MHz + state->frequency = 60; + if ((ret = mt312_initfe(fe)) < 0) + return ret; + } + } + break; + + case ID_MT312: + break; + + default: + return -EINVAL; + } + + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, p); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + } + + /* sr = (u16)(sr * 256.0 / 1000000.0) */ + sr = mt312_div(p->delsys.dvbs.symbol_rate * 4, 15625); + + /* SYM_RATE */ + buf[0] = (sr >> 8) & 0x3f; + buf[1] = (sr >> 0) & 0xff; + + /* VIT_MODE */ + buf[2] = inv_tab[p->inversion] | fec_tab[fls(p->delsys.dvbs.fec)]; + + /* QPSK_CTRL */ + buf[3] = 0x40; /* swap I and Q before QPSK demodulation */ + + if (p->delsys.dvbs.symbol_rate < 10000000) + buf[3] |= 0x04; /* use afc mode */ + + /* GO */ + buf[4] = 0x01; + + if ((ret = mt312_write(state, SYM_RATE_H, buf, sizeof(buf))) < 0) + return ret; + + mt312_reset(state, 0); + + return 0; +} + +static int mt312_get_params(struct dvb_frontend* fe, + struct dvbfe_params *p) +{ + struct mt312_state *state = fe->demodulator_priv; + int ret; + + if ((ret = mt312_get_inversion(state, &p->inversion)) < 0) + return ret; + + if ((ret = mt312_get_symbol_rate(state, &p->delsys.dvbs.symbol_rate)) < 0) + return ret; + + if ((ret = mt312_get_code_rate(state, &p->delsys.dvbs.fec)) < 0) + return ret; + + return 0; +} + +static enum dvbfe_algo mt312_get_algo(struct dvb_frontend *fe) +{ + return DVBFE_ALGO_RECOVERY; +} + static struct dvb_frontend_ops vp310_mt312_ops = { .info = { @@ -654,6 +873,12 @@ static struct dvb_frontend_ops vp310_mt3 .diseqc_send_burst = mt312_send_burst, .set_tone = mt312_set_tone, .set_voltage = mt312_set_voltage, + + .set_params = mt312_set_params, + .get_params = mt312_get_params, + .get_info = mt312_get_info, + .get_delsys = mt312_get_delsys, + .get_frontend_algo = mt312_get_algo, }; struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
_______________________________________________ linux-dvb@xxxxxxxxxxx http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb