--- v4l-dvb/linux/drivers/media/dvb/frontends/stv0297.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/stv0297.c 2006-07-23 11:40:31.000000000 +0400 @@ -232,7 +232,7 @@ static void stv0297_set_initialdemodfreq stv0297_writereg(state, 0x20, tmp); } -static int stv0297_set_qam(struct stv0297_state *state, fe_modulation_t modulation) +static int stv0297_set_qam_compat(struct stv0297_state *state, fe_modulation_t modulation) { int val = 0; @@ -266,6 +266,35 @@ static int stv0297_set_qam(struct stv029 return 0; } +static int stv0297_set_qam(struct stv0297_state *state, enum dvbfe_modulation modulation) +{ + int val = 0; + + switch (modulation) { + case DVBFE_MOD_QAM16: + val = 0; + break; + case DVBFE_MOD_QAM32: + val = 1; + break; + case DVBFE_MOD_QAM64: + val = 4; + break; + case DVBFE_MOD_QAM128: + val = 2; + break; + case DVBFE_MOD_QAM256: + val = 3; + break; + default: + return -EINVAL; + } + + stv0297_writereg_mask(state, 0x00, 0x70, val << 4); + + return 0; +} + static int stv0297_set_inversion(struct stv0297_state *state, fe_spectral_inversion_t inversion) { int val = 0; @@ -432,9 +461,10 @@ static int stv0297_set_frontend(struct d } stv0297_init(fe); - 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); } /* clear software interrupts */ @@ -497,7 +527,7 @@ static int stv0297_set_frontend(struct d stv0297_writereg_mask(state, 0x69, 0x0f, 0x00); /* set parameters */ - stv0297_set_qam(state, p->u.qam.modulation); + stv0297_set_qam_compat(state, p->u.qam.modulation); stv0297_set_symbolrate(state, p->u.qam.symbol_rate / 1000); stv0297_set_sweeprate(state, sweeprate, p->u.qam.symbol_rate / 1000); stv0297_set_carrieroffset(state, carrieroffset); @@ -664,8 +694,284 @@ error: return NULL; } -static struct dvb_frontend_ops stv0297_ops = { +static struct dvbfe_info dvbc_info = { + .name = "STV0297 DVB-C", + .delivery = DVBFE_DELSYS_DVBC, + .delsys = { + .dvbc.modulation = DVBFE_MOD_QAM16 | DVBFE_MOD_QAM32 | + DVBFE_MOD_QAM64 | DVBFE_MOD_QAM128 | + DVBFE_MOD_QAM256, + }, + + .frequency_min = 64000000, + .frequency_max = 1300000000, + .frequency_step = 62500, + .symbol_rate_min = 870000, + .symbol_rate_max = 11700000, +}; + +static int stv0297_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info) +{ + memcpy(fe_info, &dvbc_info, sizeof (dvbc_info)); + + return 0; +} + +static int stv0297_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_DVBC; + + return 0; +} + +static int stv0297_set_params(struct dvb_frontend *fe, struct dvbfe_params *p) +{ + struct stv0297_state *state = fe->demodulator_priv; + int u_threshold; + int initial_u; + int blind_u; + int delay; + int sweeprate; + int carrieroffset; + unsigned long starttime; + unsigned long timeout; + + enum fe_spectral_inversion inversion; + + switch (p->delsys.dvbc.modulation) { + case DVBFE_MOD_QAM16: + case DVBFE_MOD_QAM32: + case DVBFE_MOD_QAM64: + delay = 100; + sweeprate = 1000; + break; + + case DVBFE_MOD_QAM128: + case DVBFE_MOD_QAM256: + delay = 200; + sweeprate = 500; + break; + + default: + return -EINVAL; + } + + // determine inversion dependant parameters + inversion = p->inversion; + if (state->config->invert) + inversion = (inversion == INVERSION_ON) ? INVERSION_OFF : INVERSION_ON; + carrieroffset = -330; + switch (inversion) { + case INVERSION_OFF: + break; + + case INVERSION_ON: + sweeprate = -sweeprate; + carrieroffset = -carrieroffset; + break; + + default: + return -EINVAL; + } + + stv0297_init(fe); + 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); + } + + /* clear software interrupts */ + stv0297_writereg(state, 0x82, 0x0); + + /* set initial demodulation frequency */ + stv0297_set_initialdemodfreq(state, 7250); + + /* setup AGC */ + stv0297_writereg_mask(state, 0x43, 0x10, 0x00); + stv0297_writereg(state, 0x41, 0x00); + stv0297_writereg_mask(state, 0x42, 0x03, 0x01); + stv0297_writereg_mask(state, 0x36, 0x60, 0x00); + stv0297_writereg_mask(state, 0x36, 0x18, 0x00); + stv0297_writereg_mask(state, 0x71, 0x80, 0x80); + stv0297_writereg(state, 0x72, 0x00); + stv0297_writereg(state, 0x73, 0x00); + stv0297_writereg_mask(state, 0x74, 0x0F, 0x00); + stv0297_writereg_mask(state, 0x43, 0x08, 0x00); + stv0297_writereg_mask(state, 0x71, 0x80, 0x00); + /* setup STL */ + stv0297_writereg_mask(state, 0x5a, 0x20, 0x20); + stv0297_writereg_mask(state, 0x5b, 0x02, 0x02); + stv0297_writereg_mask(state, 0x5b, 0x02, 0x00); + stv0297_writereg_mask(state, 0x5b, 0x01, 0x00); + stv0297_writereg_mask(state, 0x5a, 0x40, 0x40); + + /* disable frequency sweep */ + stv0297_writereg_mask(state, 0x6a, 0x01, 0x00); + + /* reset deinterleaver */ + stv0297_writereg_mask(state, 0x81, 0x01, 0x01); + stv0297_writereg_mask(state, 0x81, 0x01, 0x00); + + /* ??? */ + stv0297_writereg_mask(state, 0x83, 0x20, 0x20); + stv0297_writereg_mask(state, 0x83, 0x20, 0x00); + + /* reset equaliser */ + u_threshold = stv0297_readreg(state, 0x00) & 0xf; + initial_u = stv0297_readreg(state, 0x01) >> 4; + blind_u = stv0297_readreg(state, 0x01) & 0xf; + stv0297_writereg_mask(state, 0x84, 0x01, 0x01); + stv0297_writereg_mask(state, 0x84, 0x01, 0x00); + stv0297_writereg_mask(state, 0x00, 0x0f, u_threshold); + stv0297_writereg_mask(state, 0x01, 0xf0, initial_u << 4); + stv0297_writereg_mask(state, 0x01, 0x0f, blind_u); + + /* data comes from internal A/D */ + stv0297_writereg_mask(state, 0x87, 0x80, 0x00); + + /* clear phase registers */ + stv0297_writereg(state, 0x63, 0x00); + stv0297_writereg(state, 0x64, 0x00); + stv0297_writereg(state, 0x65, 0x00); + stv0297_writereg(state, 0x66, 0x00); + stv0297_writereg(state, 0x67, 0x00); + stv0297_writereg(state, 0x68, 0x00); + stv0297_writereg_mask(state, 0x69, 0x0f, 0x00); + + /* set parameters */ + stv0297_set_qam(state, p->delsys.dvbc.modulation); + stv0297_set_symbolrate(state, p->delsys.dvbc.symbol_rate / 1000); + stv0297_set_sweeprate(state, sweeprate, p->delsys.dvbc.symbol_rate / 1000); + stv0297_set_carrieroffset(state, carrieroffset); + stv0297_set_inversion(state, inversion); + + /* kick off lock */ + /* Disable corner detection for higher QAMs */ + if (p->delsys.dvbc.modulation == DVBFE_MOD_QAM128 || + p->delsys.dvbc.modulation == DVBFE_MOD_QAM256) + stv0297_writereg_mask(state, 0x88, 0x08, 0x00); + else + stv0297_writereg_mask(state, 0x88, 0x08, 0x08); + + stv0297_writereg_mask(state, 0x5a, 0x20, 0x00); + stv0297_writereg_mask(state, 0x6a, 0x01, 0x01); + stv0297_writereg_mask(state, 0x43, 0x40, 0x40); + stv0297_writereg_mask(state, 0x5b, 0x30, 0x00); + stv0297_writereg_mask(state, 0x03, 0x0c, 0x0c); + stv0297_writereg_mask(state, 0x03, 0x03, 0x03); + stv0297_writereg_mask(state, 0x43, 0x10, 0x10); + + /* wait for WGAGC lock */ + starttime = jiffies; + timeout = jiffies + msecs_to_jiffies(2000); + while (time_before(jiffies, timeout)) { + msleep(10); + if (stv0297_readreg(state, 0x43) & 0x08) + break; + } + if (time_after(jiffies, timeout)) { + goto timeout; + } + msleep(20); + + /* wait for equaliser partial convergence */ + timeout = jiffies + msecs_to_jiffies(500); + while (time_before(jiffies, timeout)) { + msleep(10); + + if (stv0297_readreg(state, 0x82) & 0x04) { + break; + } + } + if (time_after(jiffies, timeout)) { + goto timeout; + } + + /* wait for equaliser full convergence */ + timeout = jiffies + msecs_to_jiffies(delay); + while (time_before(jiffies, timeout)) { + msleep(10); + + if (stv0297_readreg(state, 0x82) & 0x08) { + break; + } + } + if (time_after(jiffies, timeout)) { + goto timeout; + } + + /* disable sweep */ + stv0297_writereg_mask(state, 0x6a, 1, 0); + stv0297_writereg_mask(state, 0x88, 8, 0); + + /* wait for main lock */ + timeout = jiffies + msecs_to_jiffies(20); + while (time_before(jiffies, timeout)) { + msleep(10); + + if (stv0297_readreg(state, 0xDF) & 0x80) { + break; + } + } + if (time_after(jiffies, timeout)) { + goto timeout; + } + msleep(100); + + /* is it still locked after that delay? */ + if (!(stv0297_readreg(state, 0xDF) & 0x80)) { + goto timeout; + } + + /* success!! */ + stv0297_writereg_mask(state, 0x5a, 0x40, 0x00); + state->base_freq = p->frequency; + return 0; + +timeout: + stv0297_writereg_mask(state, 0x6a, 0x01, 0x00); + return 0; +} + +static int stv0297_get_params(struct dvb_frontend *fe, struct dvbfe_params *p) +{ + struct stv0297_state *state = fe->demodulator_priv; + int reg_00, reg_83; + + reg_00 = stv0297_readreg(state, 0x00); + reg_83 = stv0297_readreg(state, 0x83); + + p->frequency = state->base_freq; + p->inversion = (reg_83 & 0x08) ? INVERSION_ON : INVERSION_OFF; + if (state->config->invert) + p->inversion = (p->inversion == INVERSION_ON) ? INVERSION_OFF : INVERSION_ON; + p->delsys.dvbc.symbol_rate = stv0297_get_symbolrate(state) * 1000; + + switch ((reg_00 >> 4) & 0x7) { + case 0: + p->delsys.dvbc.modulation = DVBFE_MOD_QAM16; + break; + case 1: + p->delsys.dvbc.modulation = DVBFE_MOD_QAM32; + break; + case 2: + p->delsys.dvbc.modulation = DVBFE_MOD_QAM128; + break; + case 3: + p->delsys.dvbc.modulation = DVBFE_MOD_QAM256; + break; + case 4: + p->delsys.dvbc.modulation = DVBFE_MOD_QAM64; + break; + } + + return 0; +} + +static struct dvb_frontend_ops stv0297_ops = { + /* Info is deprecated */ .info = { .name = "ST STV0297 DVB-C", .type = FE_QAM, @@ -691,6 +997,11 @@ static struct dvb_frontend_ops stv0297_o .read_signal_strength = stv0297_read_signal_strength, .read_snr = stv0297_read_snr, .read_ucblocks = stv0297_read_ucblocks, + + .set_params = stv0297_set_params, + .get_params = stv0297_get_params, + .get_info = stv0297_get_info, + .get_delsys = stv0297_get_delsys, }; MODULE_DESCRIPTION("ST STV0297 DVB-C Demodulator driver");
_______________________________________________ linux-dvb@xxxxxxxxxxx http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb