--- v4l-dvb/linux/drivers/media/dvb/frontends/cx24110.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/cx24110.c 2006-07-23 11:37:31.000000000 +0400 @@ -178,7 +178,7 @@ static int cx24110_set_inversion (struct return 0; } -static int cx24110_set_fec (struct cx24110_state* state, fe_code_rate_t fec) +static int cx24110_set_fec_compat(struct cx24110_state* state, fe_code_rate_t fec) { /* fixme (low): error handling */ @@ -223,12 +223,84 @@ static int cx24110_set_fec (struct cx241 return 0; } -static fe_code_rate_t cx24110_get_fec (struct cx24110_state* state) +static int cx24110_set_fec(struct cx24110_state* state, enum dvbfe_fec fec) +{ + switch (fec) { + case DVBFE_FEC_AUTO: + cx24110_writereg(state, 0x37, cx24110_readreg(state, 0x37) & 0xdf); + /* clear AcqVitDis bit */ + cx24110_writereg(state, 0x18, 0xae); + /* allow all DVB standard code rates */ + cx24110_writereg(state, 0x05, (cx24110_readreg(state, 0x05) & 0xf0) | 0x3); + /* set nominal Viterbi rate 3/4 */ + cx24110_writereg(state, 0x22, (cx24110_readreg(state, 0x22) & 0xf0) | 0x3); + /* set current Viterbi rate 3/4 */ + cx24110_writereg(state, 0x1a, 0x05); cx24110_writereg(state, 0x1b, 0x06); + /* set the puncture registers for code rate 3/4 */ + break; + case DVBFE_FEC_1_2: + cx24110_writereg(state, 0x37, cx24110_readreg(state, 0x37) | 0x20); + cx24110_writereg(state, 0x05, (cx24110_readreg(state, 0x05) & 0xf0) | 1); + /* set nominal Viterbi rate */ + cx24110_writereg(state, 0x22, (cx24110_readreg(state, 0x22) & 0xf0) | 1); + /* set current Viterbi rate */ + cx24110_writereg(state, 0x1a, 0x01); + cx24110_writereg(state, 0x1b, 0x01); + /* not sure if this is the right way: I always used AutoAcq mode */ + break; + case DVBFE_FEC_2_3: + cx24110_writereg(state, 0x37, cx24110_readreg(state, 0x37) | 0x20); + cx24110_writereg(state, 0x05, (cx24110_readreg(state, 0x05) & 0xf0) | 2); + /* set nominal Viterbi rate */ + cx24110_writereg(state, 0x22, (cx24110_readreg(state, 0x22) & 0xf0) | 2); + /* set current Viterbi rate */ + cx24110_writereg(state, 0x1a, 0x02); + cx24110_writereg(state, 0x1b, 0x03); + /* not sure if this is the right way: I always used AutoAcq mode */ + break; + case DVBFE_FEC_3_4: + cx24110_writereg(state, 0x37, cx24110_readreg(state, 0x37) | 0x20); + cx24110_writereg(state, 0x05, (cx24110_readreg(state, 0x05) & 0xf0) | 3); + /* set nominal Viterbi rate */ + cx24110_writereg(state, 0x22, (cx24110_readreg(state, 0x22) & 0xf0) | 3); + /* set current Viterbi rate */ + cx24110_writereg(state, 0x1a, 0x05); + cx24110_writereg(state, 0x1b, 0x06); + /* not sure if this is the right way: I always used AutoAcq mode */ + break; + case DVBFE_FEC_5_6: + cx24110_writereg(state, 0x37, cx24110_readreg(state, 0x37) | 0x20); + cx24110_writereg(state, 0x05, (cx24110_readreg(state, 0x05) & 0xf0) | 5); + /* set nominal Viterbi rate */ + cx24110_writereg(state, 0x22, (cx24110_readreg(state, 0x22) & 0xf0) | 5); + /* set current Viterbi rate */ + cx24110_writereg(state, 0x1a, 0x15); + cx24110_writereg(state, 0x1b, 0x1a); + /* not sure if this is the right way: I always used AutoAcq mode */ + break; + case DVBFE_FEC_7_8: + cx24110_writereg(state, 0x37, cx24110_readreg(state, 0x37) | 0x20); + cx24110_writereg(state, 0x05, (cx24110_readreg(state, 0x05) & 0xf0) | 7); + /* set nominal Viterbi rate */ + cx24110_writereg(state, 0x22, (cx24110_readreg(state, 0x22) & 0xf0) | 7); + /* set current Viterbi rate */ + cx24110_writereg(state, 0x1a, 0x45); + cx24110_writereg(state, 0x1b, 0x7a); + /* not sure if this is the right way: I always used AutoAcq mode */ + break; + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static fe_code_rate_t cx24110_get_fec_compat(struct cx24110_state* state) { int i; - i=cx24110_readreg(state,0x22)&0x0f; - if(!(i&0x08)) { + i = cx24110_readreg(state, 0x22) & 0x0f; + if (!(i & 0x08)) { return FEC_1_2 + i - 1; } else { /* fixme (low): a special code rate has been selected. In theory, we need to @@ -239,6 +311,33 @@ static fe_code_rate_t cx24110_get_fec (s } } +static enum dvbfe_fec cx24110_get_fec(struct cx24110_state* state) +{ + int i; + + i = cx24110_readreg(state, 0x22) & 0x0f; + switch (i) { + case 0: + return DVBFE_FEC_NONE; + case 1: + return DVBFE_FEC_1_2; + case 2: + return DVBFE_FEC_2_3; + case 3: + return DVBFE_FEC_3_4; + case 4: + return DVBFE_FEC_4_5; + case 5: + return DVBFE_FEC_5_6; + case 6: + return DVBFE_FEC_6_7; + case 7: + return DVBFE_FEC_7_8; + default: + return DVBFE_FEC_NONE; + } +} + static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate) { /* fixme (low): add error handling */ @@ -536,13 +635,14 @@ static int cx24110_set_frontend(struct d struct cx24110_state *state = fe->demodulator_priv; - 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); } cx24110_set_inversion (state, p->inversion); - cx24110_set_fec (state, p->u.qpsk.fec_inner); + cx24110_set_fec_compat(state, p->u.qpsk.fec_inner); cx24110_set_symbolrate (state, p->u.qpsk.symbol_rate); cx24110_writereg(state,0x04,0x05); /* start aquisition */ @@ -571,7 +671,7 @@ static int cx24110_get_frontend(struct d p->frequency += afc; p->inversion = (cx24110_readreg (state, 0x22) & 0x10) ? INVERSION_ON : INVERSION_OFF; - p->u.qpsk.fec_inner = cx24110_get_fec (state); + p->u.qpsk.fec_inner = cx24110_get_fec_compat(state); return 0; } @@ -622,6 +722,95 @@ error: return NULL; } +static struct dvbfe_info dvbs_info = { + .name = "Conexant CX24110 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 = 1011, + .frequency_tolerance = 29500, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000 +}; + +static int cx24110_set_params(struct dvb_frontend* fe, + struct dvbfe_params *p) +{ + struct cx24110_state *state = fe->demodulator_priv; + + 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); + } + + cx24110_set_inversion(state, p->inversion); + cx24110_set_fec(state, p->delsys.dvbs.fec); + cx24110_set_symbolrate(state, p->delsys.dvbs.symbol_rate); + cx24110_writereg(state,0x04,0x05); /* start aquisition */ + + return 0; +} + +static int cx24110_get_params(struct dvb_frontend* fe, + struct dvbfe_params *p) +{ + struct cx24110_state *state = fe->demodulator_priv; + + s32 afc; + unsigned sclk; + +/* cannot read back tuner settings (freq). Need to have some private storage */ + + sclk = cx24110_readreg(state, 0x07) & 0x03; +/* ok, real AFC (FEDR) freq. is afc/2^24*fsamp, fsamp=45/60/80/90MHz. + * Need 64 bit arithmetic. Is thiss possible in the kernel? */ + if (sclk == 0) + sclk = 90999000L / 2L; + else if (sclk == 1) + sclk = 60666000L; + else if (sclk == 2) + sclk = 80888000L; + else + sclk = 90999000L; + + sclk >>= 8; + afc = sclk * (cx24110_readreg(state, 0x44) & 0x1f) + + ((sclk * cx24110_readreg(state, 0x45)) >> 8) + + ((sclk * cx24110_readreg(state, 0x46)) >> 16); + + p->frequency += afc; + p->inversion = (cx24110_readreg(state, 0x22) & 0x10) ? + INVERSION_ON : INVERSION_OFF; + + p->delsys.dvbs.fec = cx24110_get_fec(state); + + return 0; +} + +static int cx24110_get_info(struct dvb_frontend *fe, + struct dvbfe_info *fe_info) +{ + memcpy(fe_info, &dvbs_info, sizeof (dvbs_info)); + + return 0; +} + +static int cx24110_get_delsys(struct dvb_frontend *fe, + enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_DVBS; + + return 0; +} + static struct dvb_frontend_ops cx24110_ops = { .info = { @@ -654,6 +843,11 @@ static struct dvb_frontend_ops cx24110_o .set_tone = cx24110_set_tone, .set_voltage = cx24110_set_voltage, .diseqc_send_burst = cx24110_diseqc_send_burst, + + .set_params = cx24110_set_params, + .get_params = cx24110_get_params, + .get_info = cx24110_get_info, + .get_delsys = cx24110_get_delsys, }; module_param(debug, int, 0644);
_______________________________________________ linux-dvb@xxxxxxxxxxx http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb