diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/at76c651.c mp-bc1/linux/drivers/media/dvb/frontends/at76c651.c --- v4l-dvb/linux/drivers/media/dvb/frontends/at76c651.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/at76c651.c 2006-07-17 23:42:52.000000000 +0400 @@ -244,9 +244,10 @@ static int at76c651_set_parameters(struc int ret; struct at76c651_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); } if ((ret = at76c651_set_symbol_rate(state, p->u.qam.symbol_rate))) @@ -394,6 +395,57 @@ error: return NULL; } +static struct dvbfe_info dvbc_info = { + .name = "Atmel AT76C651B 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 = 48250000, + .frequency_max = 863250000, + .frequency_step = 62500, + .symbol_rate_min = 0, + .symbol_rate_max = 9360000, + .symbol_rate_tolerance = 4000 +}; + +static int at76c651_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info) +{ + memcpy(fe_info, &dvbc_info, sizeof (dvbc_info)); + + return 0; +} + +static int at76c651_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_DVBC, + + return 0; +} + +static int at76c651_set_params(struct dvb_frontend* fe, struct dvbfe_params *p) +{ + int ret; + struct at76c651_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 ((ret = at76c651_set_symbol_rate(state, p->delsys.dvbc.symbol_rate))) + return ret; + + if ((ret = at76c651_set_inversion(state, p->inversion))) + return ret; + + return at76c651_set_auto_config(state); +} + static struct dvb_frontend_ops at76c651_ops = { .info = { @@ -414,19 +466,20 @@ static struct dvb_frontend_ops at76c651_ FE_CAN_MUTE_TS | FE_CAN_QAM_256 | FE_CAN_RECOVER }, - .release = at76c651_release, - - .init = at76c651_set_defaults, - .i2c_gate_ctrl = at76c651_i2c_gate_ctrl, - - .set_frontend = at76c651_set_parameters, - .get_tune_settings = at76c651_get_tune_settings, - - .read_status = at76c651_read_status, - .read_ber = at76c651_read_ber, - .read_signal_strength = at76c651_read_signal_strength, - .read_snr = at76c651_read_snr, - .read_ucblocks = at76c651_read_ucblocks, + .release = at76c651_release, + .init = at76c651_set_defaults, + .i2c_gate_ctrl = at76c651_i2c_gate_ctrl, + .set_frontend = at76c651_set_parameters, + .get_tune_settings = at76c651_get_tune_settings, + .read_status = at76c651_read_status, + .read_ber = at76c651_read_ber, + .read_signal_strength = at76c651_read_signal_strength, + .read_snr = at76c651_read_snr, + .read_ucblocks = at76c651_read_ucblocks, + + .set_params = at76c651_set_params, + .get_info = at76c651_get_info, + .get_delsys = at76c651_det_delsys, }; module_param(debug, int, 0644); diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/bcm3510.c mp-bc1/linux/drivers/media/dvb/frontends/bcm3510.c --- v4l-dvb/linux/drivers/media/dvb/frontends/bcm3510.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/bcm3510.c 2006-07-17 23:43:00.000000000 +0400 @@ -488,7 +488,7 @@ static int bcm3510_set_freq(struct bcm35 } static int bcm3510_set_frontend(struct dvb_frontend* fe, - struct dvb_frontend_parameters *p) + struct dvb_frontend_parameters *p) { struct bcm3510_state* st = fe->demodulator_priv; struct bcm3510_hab_cmd_ext_acquire cmd; @@ -825,6 +825,119 @@ error: } EXPORT_SYMBOL(bcm3510_attach); +static int bcm3510_set_params(struct dvb_frontend* fe, + struct dvbfe_params *p) +{ + struct bcm3510_state* st = fe->demodulator_priv; + struct bcm3510_hab_cmd_ext_acquire cmd; + struct bcm3510_hab_cmd_bert_control bert; + int ret; + + memset(&cmd,0,sizeof(cmd)); + switch (p->delsys.atsc.modulation) { + case QAM_256: + cmd.ACQUIRE0.MODE = 0x1; + cmd.ACQUIRE1.SYM_RATE = 0x1; + cmd.ACQUIRE1.IF_FREQ = 0x1; + break; + case QAM_64: + cmd.ACQUIRE0.MODE = 0x2; + cmd.ACQUIRE1.SYM_RATE = 0x2; + cmd.ACQUIRE1.IF_FREQ = 0x1; + break; +/* case QAM_256: + cmd.ACQUIRE0.MODE = 0x3; + break; + case QAM_128: + cmd.ACQUIRE0.MODE = 0x4; + break; + case QAM_64: + cmd.ACQUIRE0.MODE = 0x5; + break; + case QAM_32: + cmd.ACQUIRE0.MODE = 0x6; + break; + case QAM_16: + cmd.ACQUIRE0.MODE = 0x7; + break;*/ + case VSB_8: + cmd.ACQUIRE0.MODE = 0x8; + cmd.ACQUIRE1.SYM_RATE = 0x0; + cmd.ACQUIRE1.IF_FREQ = 0x0; + break; + case VSB_16: + cmd.ACQUIRE0.MODE = 0x9; + cmd.ACQUIRE1.SYM_RATE = 0x0; + cmd.ACQUIRE1.IF_FREQ = 0x0; + default: + return -EINVAL; + }; + cmd.ACQUIRE0.OFFSET = 0; + cmd.ACQUIRE0.NTSCSWEEP = 1; + cmd.ACQUIRE0.FA = 1; + cmd.ACQUIRE0.BW = 0; + +/* if (enableOffset) { + cmd.IF_OFFSET0 = xx; + cmd.IF_OFFSET1 = xx; + + cmd.SYM_OFFSET0 = xx; + cmd.SYM_OFFSET1 = xx; + if (enableNtscSweep) { + cmd.NTSC_OFFSET0; + cmd.NTSC_OFFSET1; + } + } */ + bcm3510_do_hab_cmd(st, CMD_ACQUIRE, MSGID_EXT_TUNER_ACQUIRE, (u8 *) &cmd, sizeof(cmd), NULL, 0); + +/* doing it with different MSGIDs, data book and source differs */ + bert.BE = 0; + bert.unused = 0; + bcm3510_do_hab_cmd(st, CMD_STATE_CONTROL, MSGID_BERT_CONTROL, (u8 *) &bert, sizeof(bert), NULL, 0); + bcm3510_do_hab_cmd(st, CMD_STATE_CONTROL, MSGID_BERT_SET, (u8 *) &bert, sizeof(bert), NULL, 0); + + bcm3510_bert_reset(st); + + if ((ret = bcm3510_set_freq(st,p->frequency)) < 0) + return ret; + + memset(&st->status1,0,sizeof(st->status1)); + memset(&st->status2,0,sizeof(st->status2)); + st->status_check_interval = 500; + +/* Give the AP some time */ + msleep(200); + + return 0; +} + +static struct dvbfe_info atsc_info = { + .name = "Broadcom BCM3510 ATSC", + .delivery = DVBFE_DELSYS_ATSC, + .delsys = { + .atsc.modulation = DVBFE_MOD_VSB8 | DVBFE_MOD_VSB16 | + DVBFE_MOD_QAM16 | DVBFE_MOD_QAM64 | + DVBFE_MOD_QAM128 | DVBFE_MOD_QAM256 + }, + + .frequency_min = 54000000, + .frequency_max = 803000000, + .frequency_step = 0 +}; + +static int bcm3510_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info) +{ + memcpy(fe_info, &atsc_info, sizeof (atsc_info)); + + return 0; +} + +static int bcm3510_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_ATSC; + + return 0; +} static struct dvb_frontend_ops bcm3510_ops = { .info = { @@ -854,6 +967,10 @@ static struct dvb_frontend_ops bcm3510_o .read_signal_strength = bcm3510_read_signal_strength, .read_snr = bcm3510_read_snr, .read_ucblocks = bcm3510_read_unc, + + .set_params = bcm3510_set_params, + .get_info = bcm3510_get_info, + .get_delsys = bcm3510_get_delsys, }; MODULE_DESCRIPTION("Broadcom BCM3510 ATSC (8VSB/16VSB & ITU J83 AnnexB FEC QAM64/256) demodulator driver"); diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/bsbe1.h mp-bc1/linux/drivers/media/dvb/frontends/bsbe1.h --- v4l-dvb/linux/drivers/media/dvb/frontends/bsbe1.h 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/bsbe1.h 2006-07-05 19:29:13.000000000 +0400 @@ -89,7 +89,30 @@ static int alps_bsbe1_set_symbol_rate(st return 0; } -static int alps_bsbe1_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) +static int alps_bsbe1_tuner_set_params_compat(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) +{ + int ret; + u8 data[4]; + u32 div; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; + struct i2c_adapter *i2c = fe->tuner_priv; + + if ((params->frequency < 950000) || (params->frequency > 2150000)) + return -EINVAL; + + div = (params->frequency + (125 - 1)) / 125; // round correctly + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0x80 | ((div & 0x18000) >> 10) | 4; + data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + ret = i2c_transfer(i2c, &msg, 1); + return (ret != 1) ? -EIO : 0; +} + +static int alps_bsbe1_tuner_set_params(struct dvb_frontend* fe, struct dvbfe_params *params) { int ret; u8 data[4]; diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/bsru6.h mp-bc1/linux/drivers/media/dvb/frontends/bsru6.h --- v4l-dvb/linux/drivers/media/dvb/frontends/bsru6.h 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/bsru6.h 2006-07-05 19:29:42.000000000 +0400 @@ -101,7 +101,33 @@ static int alps_bsru6_set_symbol_rate(st return 0; } -static int alps_bsru6_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +static int alps_bsru6_tuner_set_params_compat(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + u8 buf[4]; + u32 div; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; + struct i2c_adapter *i2c = fe->tuner_priv; + + if ((params->frequency < 950000) || (params->frequency > 2150000)) + return -EINVAL; + + div = (params->frequency + (125 - 1)) / 125; // round correctly + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4; + buf[3] = 0xC4; + + if (params->frequency > 1530000) + buf[3] = 0xc0; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if (i2c_transfer(i2c, &msg, 1) != 1) + return -EIO; + return 0; +} + +static int alps_bsru6_tuner_set_params(struct dvb_frontend *fe, struct dvbfe_params *params) { u8 buf[4]; u32 div; diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/cx22700.c mp-bc1/linux/drivers/media/dvb/frontends/cx22700.c --- v4l-dvb/linux/drivers/media/dvb/frontends/cx22700.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/cx22700.c 2006-07-17 23:43:15.000000000 +0400 @@ -122,7 +122,8 @@ static int cx22700_set_inversion (struct } } -static int cx22700_set_tps (struct cx22700_state *state, struct dvb_ofdm_parameters *p) +static int cx22700_set_tps_compat(struct cx22700_state *state, + struct dvb_ofdm_parameters *p) { static const u8 qam_tab [4] = { 0, 1, 0, 2 }; static const u8 fec_tab [6] = { 0, 1, 2, 0, 3, 4 }; @@ -185,7 +186,177 @@ static int cx22700_set_tps (struct cx227 return 0; } -static int cx22700_get_tps (struct cx22700_state* state, struct dvb_ofdm_parameters *p) +static int cx22700_set_tps(struct cx22700_state *state, struct dvbt_params *p) +{ + u8 val = 0; + + dprintk ("%s\n", __FUNCTION__); + + if (p->code_rate_HP < DVBFE_FEC_1_2 || p->code_rate_HP > DVBFE_FEC_7_8) + return -EINVAL; + + if (p->code_rate_LP < DVBFE_FEC_1_2 || p->code_rate_LP > DVBFE_FEC_7_8) + return -EINVAL; + + if (p->code_rate_HP == DVBFE_FEC_4_5 || p->code_rate_LP == DVBFE_FEC_4_5) + return -EINVAL; + + if (p->guard_interval < DVBFE_GUARD_INTERVAL_1_32 || + p->guard_interval > DVBFE_GUARD_INTERVAL_1_4) + return -EINVAL; + + if (p->transmission_mode != DVBFE_TRANSMISSION_MODE_2K && + p->transmission_mode != DVBFE_TRANSMISSION_MODE_8K) + return -EINVAL; + + if (p->constellation != DVBFE_MOD_QPSK && + p->constellation != DVBFE_MOD_QAM16 && + p->constellation != DVBFE_MOD_QAM64) + return -EINVAL; + + if (p->bandwidth < DVBFE_BANDWIDTH_8_MHZ && + p->bandwidth > DVBFE_BANDWIDTH_6_MHZ) + return -EINVAL; + + if (p->bandwidth == DVBFE_BANDWIDTH_7_MHZ) + cx22700_writereg (state, 0x09, cx22700_readreg (state, 0x09 | 0x10)); + else + cx22700_writereg (state, 0x09, cx22700_readreg (state, 0x09 & ~0x10)); + + switch (p->constellation) { + case DVBFE_MOD_QPSK: + val = 0; + break; + case DVBFE_MOD_QAM16: + val = 1; + break; + case DVBFE_MOD_QAM64: + val = 2; + break; + default: + break; + } + + switch (p->hierarchy) { + case DVBFE_HIERARCHY_OFF: + val |= 0; + break; + case DVBFE_HIERARCHY_ON: + switch(p->alpha) { + case DVBFE_ALPHA_1: + val |= 1; + break; + case DVBFE_ALPHA_2: + val |= 2; + break; + case DVBFE_ALPHA_4: + val |= 3; + break; + default: + break; + } + break; + case DVBFE_HIERARCHY_AUTO: + val |= 4; + break; + default: + break; + } + + cx22700_writereg (state, 0x04, val); + + switch (p->code_rate_HP) { + case DVBFE_FEC_1_2: + val = (0 << 3); + break; + case DVBFE_FEC_2_3: + val = (1 << 3); + break; + case DVBFE_FEC_3_4: + val = (2 << 3); + break; + case DVBFE_FEC_5_6: + val = (3 << 3); + break; + case DVBFE_FEC_7_8: + val = (4 << 3); + break; + case DVBFE_FEC_NONE: + case DVBFE_FEC_AUTO: + break; + default: + break; + } + + switch (p->code_rate_LP) { + case DVBFE_FEC_1_2: + val |= 0; + break; + case DVBFE_FEC_2_3: + val |= 1; + break; + case DVBFE_FEC_3_4: + val |= 2; + break; + case DVBFE_FEC_5_6: + val |= 3; + break; + case DVBFE_FEC_7_8: + val |= 4; + break; + case DVBFE_FEC_NONE: + case DVBFE_FEC_AUTO: + break; + default: + break; + } + + cx22700_writereg (state, 0x05, val); + + switch (p->guard_interval) { + case DVBFE_GUARD_INTERVAL_1_32: + val = (0 << 2); + break; + case DVBFE_GUARD_INTERVAL_1_16: + val = (1 << 2); + break; + case DVBFE_GUARD_INTERVAL_1_8: + val = (2 << 2); + break; + case DVBFE_GUARD_INTERVAL_1_4: + val = (3 << 2); + break; + case DVBFE_GUARD_INTERVAL_AUTO: + val = (4 << 2); + break; + default: + break; + } + + switch (p->transmission_mode) { + case DVBFE_TRANSMISSION_MODE_2K: + val |= 0; + break; + case DVBFE_TRANSMISSION_MODE_8K: + val |= 1; + break; + case DVBFE_TRANSMISSION_MODE_AUTO: + val |= 2; + break; + default: + break; + } + + cx22700_writereg (state, 0x06, val); + + cx22700_writereg (state, 0x08, 0x04 | 0x02); /* use user tps parameters */ + cx22700_writereg (state, 0x08, 0x04); /* restart aquisition */ + + return 0; +} + +static int cx22700_get_tps_compat (struct cx22700_state* state, + struct dvb_ofdm_parameters *p) { static const fe_modulation_t qam_tab [3] = { QPSK, QAM_16, QAM_64 }; static const fe_code_rate_t fec_tab [5] = { FEC_1_2, FEC_2_3, FEC_3_4, @@ -229,6 +400,51 @@ static int cx22700_get_tps (struct cx227 return 0; } +static int cx22700_get_tps(struct cx22700_state* state, + struct dvbt_params *p) +{ + static const fe_modulation_t qam_tab [3] = { QPSK, QAM_16, QAM_64 }; + static const fe_code_rate_t fec_tab [5] = { FEC_1_2, FEC_2_3, FEC_3_4, + FEC_5_6, FEC_7_8 }; + u8 val; + + dprintk ("%s\n", __FUNCTION__); + + if (!(cx22700_readreg(state, 0x07) & 0x20)) /* tps valid? */ + return -EAGAIN; + + val = cx22700_readreg (state, 0x01); + + if ((val & 0x7) > 4) + p->hierarchy = DVBFE_HIERARCHY_AUTO; + else + p->hierarchy = (val & 0x7); + + if (((val >> 3) & 0x3) > 2) + p->constellation = DVBFE_MOD_QAMAUTO; + else + p->constellation = qam_tab[(val >> 3) & 0x3]; + + val = cx22700_readreg (state, 0x02); + + if (((val >> 3) & 0x07) > 4) + p->code_rate_HP = DVBFE_FEC_AUTO; + else + p->code_rate_HP = fec_tab[(val >> 3) & 0x07]; + + if ((val & 0x07) > 4) + p->code_rate_LP = DVBFE_FEC_AUTO; + else + p->code_rate_LP = fec_tab[val & 0x07]; + + val = cx22700_readreg (state, 0x03); + + p->guard_interval = ((val >> 6) & 0x3); + p->transmission_mode = ((val >> 5) & 0x1); + + return 0; +} + static int cx22700_init (struct dvb_frontend* fe) { struct cx22700_state* state = fe->demodulator_priv; @@ -326,13 +542,14 @@ static int cx22700_set_frontend(struct d cx22700_writereg (state, 0x00, 0x02); /* XXX CHECKME: soft reset*/ cx22700_writereg (state, 0x00, 0x00); - 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); } cx22700_set_inversion (state, p->inversion); - cx22700_set_tps (state, &p->u.ofdm); + cx22700_set_tps_compat(state, &p->u.ofdm); cx22700_writereg (state, 0x37, 0x01); /* PAL loop filter off */ cx22700_writereg (state, 0x00, 0x01); /* restart acquire */ @@ -345,7 +562,7 @@ static int cx22700_get_frontend(struct d u8 reg09 = cx22700_readreg (state, 0x09); p->inversion = reg09 & 0x1 ? INVERSION_ON : INVERSION_OFF; - return cx22700_get_tps (state, &p->u.ofdm); + return cx22700_get_tps_compat(state, &p->u.ofdm); } static int cx22700_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) @@ -401,6 +618,66 @@ error: return NULL; } +static int cx22700_set_params(struct dvb_frontend* fe, + struct dvbfe_params *p) +{ + struct cx22700_state* state = fe->demodulator_priv; + + cx22700_writereg (state, 0x00, 0x02); /* XXX CHECKME: soft reset*/ + cx22700_writereg (state, 0x00, 0x00); + + 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); + } + + cx22700_set_inversion (state, p->inversion); + cx22700_set_tps (state, &p->delsys.dvbt); + cx22700_writereg (state, 0x37, 0x01); /* PAL loop filter off */ + cx22700_writereg (state, 0x00, 0x01); /* restart acquire */ + + return 0; +} + +static int cx22700_get_params(struct dvb_frontend* fe, + struct dvbfe_params *p) +{ + struct cx22700_state* state = fe->demodulator_priv; + u8 reg09 = cx22700_readreg (state, 0x09); + + p->inversion = reg09 & 0x1 ? INVERSION_ON : INVERSION_OFF; + return cx22700_get_tps(state, &p->delsys.dvbt); +} + +static struct dvbfe_info dvbt_info = { + .name = "Conexant CX22700 DVB-T", + .delivery = DVBFE_DELSYS_DVBT, + .delsys = { + .dvbt.modulation = DVBFE_MOD_OFDM, + .dvbt.stream_priority = DVBFE_STREAM_PRIORITY_HP | + DVBFE_STREAM_PRIORITY_LP + }, + + .frequency_min = 470000000, + .frequency_max = 860000000, + .frequency_step = 166667, +}; + +static int cx22700_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info) +{ + memcpy(fe_info, &dvbt_info, sizeof (dvbt_info)); + + return 0; +} + +static int cx22700_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_DVBT; + + return 0; +} + static struct dvb_frontend_ops cx22700_ops = { .info = { @@ -429,6 +706,11 @@ static struct dvb_frontend_ops cx22700_o .read_signal_strength = cx22700_read_signal_strength, .read_snr = cx22700_read_snr, .read_ucblocks = cx22700_read_ucblocks, + + .set_params = cx22700_set_params, + .get_params = cx22700_get_params, + .get_info = cx22700_get_info, + .get_delsys = cx22700_get_delsys, }; module_param(debug, int, 0644); diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/cx22702.c mp-bc1/linux/drivers/media/dvb/frontends/cx22702.c --- v4l-dvb/linux/drivers/media/dvb/frontends/cx22702.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/cx22702.c 2006-07-17 23:43:20.000000000 +0400 @@ -139,7 +139,8 @@ static int cx22702_set_inversion (struct } /* Retrieve the demod settings */ -static int cx22702_get_tps (struct cx22702_state *state, struct dvb_ofdm_parameters *p) +static int cx22702_get_tps_compat(struct cx22702_state *state, + struct dvb_ofdm_parameters *p) { u8 val; @@ -193,6 +194,108 @@ static int cx22702_get_tps (struct cx227 return 0; } +static int cx22702_get_tps(struct cx22702_state *state, + struct dvbt_params *p) +{ + u8 val; + + /* Make sure the TPS regs are valid */ + if (!(cx22702_readreg(state, 0x0A) & 0x20)) + return -EAGAIN; + + val = cx22702_readreg(state, 0x01); + switch ((val &0x18) >> 3) { + case 0: + p->constellation = DVBFE_MOD_QPSK; + break; + case 1: + p->constellation = DVBFE_MOD_QAM16; + break; + case 2: + p->constellation = DVBFE_MOD_QAM64; + break; + } + switch (val & 0x07) { + case 0: + p->hierarchy = DVBFE_HIERARCHY_OFF; + break; + case 1: + p->alpha = DVBFE_ALPHA_1; + p->hierarchy = DVBFE_HIERARCHY_ON; + break; + case 2: + p->alpha = DVBFE_ALPHA_2; + p->hierarchy = DVBFE_HIERARCHY_ON; + break; + case 3: + p->alpha = DVBFE_ALPHA_4; + p->hierarchy = DVBFE_HIERARCHY_ON; + break; + } + + val = cx22702_readreg(state, 0x02); + switch ((val & 0x38) >> 3) { + case 0: + p->code_rate_HP = DVBFE_FEC_1_2; + break; + case 1: + p->code_rate_HP = DVBFE_FEC_2_3; + break; + case 2: + p->code_rate_HP = DVBFE_FEC_3_4; + break; + case 3: + p->code_rate_HP = DVBFE_FEC_5_6; + break; + case 4: + p->code_rate_HP = DVBFE_FEC_7_8; + break; + } + switch (val & 0x07) { + case 0: + p->code_rate_LP = DVBFE_FEC_1_2; + break; + case 1: + p->code_rate_LP = DVBFE_FEC_2_3; + break; + case 2: + p->code_rate_LP = DVBFE_FEC_3_4; + break; + case 3: + p->code_rate_LP = DVBFE_FEC_5_6; + break; + case 4: + p->code_rate_LP = DVBFE_FEC_7_8; + break; + } + + val = cx22702_readreg (state, 0x03); + switch ((val & 0x0c) >> 2) { + case 0: + p->guard_interval = DVBFE_GUARD_INTERVAL_1_32; + break; + case 1: + p->guard_interval = DVBFE_GUARD_INTERVAL_1_16; + break; + case 2: + p->guard_interval = DVBFE_GUARD_INTERVAL_1_8; + break; + case 3: + p->guard_interval = DVBFE_GUARD_INTERVAL_1_4; + break; + } + switch (val & 0x03) { + case 0: + p->transmission_mode = DVBFE_TRANSMISSION_MODE_2K; + break; + case 1: + p->transmission_mode = DVBFE_TRANSMISSION_MODE_8K; + break; + } + + return 0; +} + static int cx22702_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) { struct cx22702_state* state = fe->demodulator_priv; @@ -209,9 +312,10 @@ static int cx22702_set_tps (struct dvb_f u8 val; struct cx22702_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); } /* set inversion */ @@ -447,7 +551,7 @@ static int cx22702_get_frontend(struct d u8 reg0C = cx22702_readreg (state, 0x0C); p->inversion = reg0C & 0x1 ? INVERSION_ON : INVERSION_OFF; - return cx22702_get_tps (state, &p->u.ofdm); + return cx22702_get_tps_compat(state, &p->u.ofdm); } static int cx22702_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) @@ -493,6 +597,223 @@ error: return NULL; } +static struct dvbfe_info dvbt_info = { + .name = "Conexant CX22702 DVB-T", + .delivery = DVBFE_DELSYS_DVBT, + .delsys = { + .dvbt.modulation = DVBFE_MOD_OFDM, + .dvbt.stream_priority = DVBFE_STREAM_PRIORITY_HP | + DVBFE_STREAM_PRIORITY_LP, + }, + + .frequency_min = 177000000, + .frequency_max = 858000000, + .frequency_step = 166666, +}; + +static int cx22702_set_params(struct dvb_frontend* fe, + struct dvbfe_params *p) +{ + u8 val; + struct cx22702_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); + } + + /* set inversion */ + cx22702_set_inversion (state, p->inversion); + + /* set bandwidth */ + switch(p->delsys.dvbt.bandwidth) { + case DVBFE_BANDWIDTH_6_MHZ: + cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xcf) | 0x20 ); + break; + case DVBFE_BANDWIDTH_7_MHZ: + cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xcf) | 0x10 ); + break; + case DVBFE_BANDWIDTH_8_MHZ: + cx22702_writereg(state, 0x0C, cx22702_readreg(state, 0x0C) &0xcf ); + break; + default: + dprintk ("%s: invalid bandwidth\n",__FUNCTION__); + return -EINVAL; + } + + + p->delsys.dvbt.code_rate_LP = FEC_AUTO; //temp hack as manual not working + + /* use auto configuration? */ + if((p->delsys.dvbt.hierarchy == DVBFE_HIERARCHY_AUTO) || + (p->delsys.dvbt.constellation == DVBFE_MOD_QAMAUTO) || + (p->delsys.dvbt.code_rate_HP == DVBFE_FEC_AUTO) || + (p->delsys.dvbt.code_rate_LP == DVBFE_FEC_AUTO) || + (p->delsys.dvbt.guard_interval == DVBFE_GUARD_INTERVAL_AUTO) || + (p->delsys.dvbt.transmission_mode == DVBFE_TRANSMISSION_MODE_AUTO) ) { + + /* TPS Source - use hardware driven values */ + cx22702_writereg(state, 0x06, 0x10); + cx22702_writereg(state, 0x07, 0x9); + cx22702_writereg(state, 0x08, 0xC1); + cx22702_writereg(state, 0x0B, cx22702_readreg(state, 0x0B) & 0xfc ); + cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40 ); + cx22702_writereg(state, 0x00, 0x01); /* Begin aquisition */ + dprintk("%s: Autodetecting\n",__FUNCTION__); + return 0; + } + + /* manually programmed values */ + val = 0; + switch (p->delsys.dvbt.constellation) { + case DVBFE_MOD_QPSK: + val = (val & 0xe7); + break; + case DVBFE_MOD_QAM16: + val = (val & 0xe7) | 0x08; + break; + case DVBFE_MOD_QAM64: + val = (val & 0xe7) | 0x10; + break; + default: + dprintk ("%s: invalid constellation\n",__FUNCTION__); + return -EINVAL; + } + switch (p->delsys.dvbt.hierarchy) { + case DVBFE_HIERARCHY_OFF: + val = (val & 0xf8); + break; + case DVBFE_HIERARCHY_ON: + switch (p->delsys.dvbt.alpha) { + case DVBFE_ALPHA_1: + val = (val & 0xf8) | 1; + break; + case DVBFE_ALPHA_2: + val = (val & 0xf8) | 2; + break; + case DVBFE_ALPHA_4: + val = (val & 0xf8) | 3 ; + break; + } + break; + case DVBFE_HIERARCHY_AUTO: + break; + default: + dprintk ("%s: invalid hierarchy\n", __FUNCTION__); + return -EINVAL; + } + cx22702_writereg (state, 0x06, val); + + val = 0; + switch (p->delsys.dvbt.code_rate_HP) { + case DVBFE_FEC_NONE: + case DVBFE_FEC_1_2: + val = (val & 0xc7); + break; + case DVBFE_FEC_2_3: + val = (val & 0xc7) | 0x08; + break; + case DVBFE_FEC_3_4: + val = (val & 0xc7) | 0x10; + break; + case DVBFE_FEC_5_6: + val = (val & 0xc7) | 0x18; + break; + case DVBFE_FEC_7_8: + val = (val & 0xc7) | 0x20; + break; + default: + dprintk ("%s: invalid code_rate_HP\n",__FUNCTION__); + return -EINVAL; + } + switch (p->delsys.dvbt.code_rate_LP) { + case DVBFE_FEC_NONE: + case DVBFE_FEC_1_2: + val = (val & 0xf8); + break; + case DVBFE_FEC_2_3: + val = (val & 0xf8) | 1; + break; + case DVBFE_FEC_3_4: + val = (val & 0xf8) | 2; + break; + case DVBFE_FEC_5_6: + val = (val & 0xf8) | 3; + break; + case DVBFE_FEC_7_8: + val = (val & 0xf8) | 4; + break; + default: + dprintk ("%s: invalid code_rate_LP\n",__FUNCTION__); + return -EINVAL; + } + cx22702_writereg (state, 0x07, val); + + val = 0; + switch (p->delsys.dvbt.guard_interval) { + case DVBFE_GUARD_INTERVAL_1_32: + val = (val & 0xf3); + break; + case DVBFE_GUARD_INTERVAL_1_16: + val = (val & 0xf3) | 0x04; + break; + case DVBFE_GUARD_INTERVAL_1_8: + val = (val & 0xf3) | 0x08; + break; + case DVBFE_GUARD_INTERVAL_1_4: + val = (val & 0xf3) | 0x0c; + break; + default: + dprintk ("%s: invalid guard_interval\n",__FUNCTION__); + return -EINVAL; + } + switch (p->delsys.dvbt.transmission_mode) { + case DVBFE_TRANSMISSION_MODE_2K: + val = (val & 0xfc); + break; + case DVBFE_TRANSMISSION_MODE_8K: + val = (val & 0xfc) | 1; + break; + default: + dprintk ("%s: invalid transmission_mode\n",__FUNCTION__); + return -EINVAL; + } + cx22702_writereg(state, 0x08, val); + cx22702_writereg(state, 0x0B, (cx22702_readreg(state, 0x0B) & 0xfc) | 0x02 ); + cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40 ); + + /* Begin channel aquisition */ + cx22702_writereg(state, 0x00, 0x01); + + return 0; +} + +static int cx22702_get_params(struct dvb_frontend* fe, + struct dvbfe_params *p) +{ + struct cx22702_state* state = fe->demodulator_priv; + + u8 reg0C = cx22702_readreg (state, 0x0C); + + p->inversion = reg0C & 0x1 ? INVERSION_ON : INVERSION_OFF; + return cx22702_get_tps(state, &p->delsys.dvbt); +} + +static int cx22702_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info) +{ + memcpy(fe_info, &dvbt_info, sizeof (dvbt_info)); + + return 0; +} + +static int cx22702_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_DVBT; + + return 0; +} + static struct dvb_frontend_ops cx22702_ops = { .info = { @@ -522,6 +843,11 @@ static struct dvb_frontend_ops cx22702_o .read_signal_strength = cx22702_read_signal_strength, .read_snr = cx22702_read_snr, .read_ucblocks = cx22702_read_ucblocks, + + .set_params = cx22702_set_params, + .get_params = cx22702_get_params, + .get_info = cx22702_get_info, + .get_delsys = cx22702_get_delsys, }; module_param(debug, int, 0644); diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/cx24110.c mp-bc1/linux/drivers/media/dvb/frontends/cx24110.c --- 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-17 23:43:29.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,22 @@ 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; + if (!(i & 0x08)) { + return DVBFE_FEC_1_2 + i - 1; + } else { +/* fixme (low): a special code rate has been selected. In theory, we need to + return a denominator value, a numerator value, and a pair of puncture + maps to correctly describe this mode. But this should never happen in + practice, because it cannot be set by cx24110_get_fec. */ + return DVBFE_FEC_NONE; + } +} + static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate) { /* fixme (low): add error handling */ @@ -536,13 +624,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 +660,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 +711,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 +832,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); diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/cx24123.c mp-bc1/linux/drivers/media/dvb/frontends/cx24123.c --- v4l-dvb/linux/drivers/media/dvb/frontends/cx24123.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/cx24123.c 2006-07-17 23:43:33.000000000 +0400 @@ -325,7 +325,62 @@ static int cx24123_get_inversion(struct return 0; } -static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec) +static int cx24123_set_fec(struct cx24123_state* state, enum dvbfe_fec fec) +{ + u8 nom_reg = cx24123_readreg(state, 0x0e) & ~0x07; + + if ( (fec < DVBFE_FEC_NONE) || (fec > DVBFE_FEC_AUTO) ) + fec = DVBFE_FEC_AUTO; + + switch (fec) { + case DVBFE_FEC_1_2: + dprintk("%s: set FEC to 1/2\n",__FUNCTION__); + cx24123_writereg(state, 0x0e, nom_reg | 0x01); + cx24123_writereg(state, 0x0f, 0x02); + break; + case DVBFE_FEC_2_3: + dprintk("%s: set FEC to 2/3\n",__FUNCTION__); + cx24123_writereg(state, 0x0e, nom_reg | 0x02); + cx24123_writereg(state, 0x0f, 0x04); + break; + case DVBFE_FEC_3_4: + dprintk("%s: set FEC to 3/4\n",__FUNCTION__); + cx24123_writereg(state, 0x0e, nom_reg | 0x03); + cx24123_writereg(state, 0x0f, 0x08); + break; + case DVBFE_FEC_4_5: + dprintk("%s: set FEC to 4/5\n",__FUNCTION__); + cx24123_writereg(state, 0x0e, nom_reg | 0x04); + cx24123_writereg(state, 0x0f, 0x10); + break; + case DVBFE_FEC_5_6: + dprintk("%s: set FEC to 5/6\n",__FUNCTION__); + cx24123_writereg(state, 0x0e, nom_reg | 0x05); + cx24123_writereg(state, 0x0f, 0x20); + break; + case DVBFE_FEC_6_7: + dprintk("%s: set FEC to 6/7\n",__FUNCTION__); + cx24123_writereg(state, 0x0e, nom_reg | 0x06); + cx24123_writereg(state, 0x0f, 0x40); + break; + case DVBFE_FEC_7_8: + dprintk("%s: set FEC to 7/8\n",__FUNCTION__); + cx24123_writereg(state, 0x0e, nom_reg | 0x07); + cx24123_writereg(state, 0x0f, 0x80); + break; + case DVBFE_FEC_AUTO: + dprintk("%s: set FEC to auto\n",__FUNCTION__); + cx24123_writereg(state, 0x0f, 0xfe); + break; + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static int cx24123_set_fec_compat(struct cx24123_state* state, + fe_code_rate_t fec) { u8 nom_reg = cx24123_readreg(state, 0x0e) & ~0x07; @@ -379,7 +434,7 @@ static int cx24123_set_fec(struct cx2412 return 0; } -static int cx24123_get_fec(struct cx24123_state* state, fe_code_rate_t *fec) +static int cx24123_get_fec_compat(struct cx24123_state* state, fe_code_rate_t *fec) { int ret; @@ -418,6 +473,46 @@ static int cx24123_get_fec(struct cx2412 return 0; } +static int cx24123_get_fec(struct cx24123_state* state, + enum dvbfe_fec *fec) +{ + int ret; + + ret = cx24123_readreg (state, 0x1b); + if (ret < 0) + return ret; + ret = ret & 0x07; + + switch (ret) { + case 1: + *fec = DVBFE_FEC_1_2; + break; + case 2: + *fec = DVBFE_FEC_2_3; + break; + case 3: + *fec = DVBFE_FEC_3_4; + break; + case 4: + *fec = DVBFE_FEC_4_5; + break; + case 5: + *fec = DVBFE_FEC_5_6; + break; + case 6: + *fec = DVBFE_FEC_6_7; + break; + case 7: + *fec = DVBFE_FEC_7_8; + break; + default: + /* this can happen when there's no lock */ + *fec = DVBFE_FEC_NONE; + } + + return 0; +} + /* Approximation of closest integer of log2(a/b). It actually gives the lowest integer i such that 2^i >= round(a/b) */ static u32 cx24123_int_log2(u32 a, u32 b) @@ -507,7 +602,8 @@ static int cx24123_set_symbolrate(struct * Based on the required frequency and symbolrate, the tuner AGC has to be configured * and the correct band selected. Calculate those values */ -static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) +static int cx24123_pll_calculate_compat(struct dvb_frontend* fe, + struct dvb_frontend_parameters *p) { struct cx24123_state *state = fe->demodulator_priv; u32 ndiv = 0, adiv = 0, vco_div = 0; @@ -569,11 +665,76 @@ static int cx24123_pll_calculate(struct return 0; } +static int cx24123_pll_calculate(struct dvb_frontend* fe, + struct dvbfe_params *p) +{ + struct cx24123_state *state = fe->demodulator_priv; + u32 ndiv = 0, adiv = 0, vco_div = 0; + int i = 0; + int pump = 2; + int band = 0; + int num_bands = sizeof (cx24123_bandselect_vals) / + sizeof(cx24123_bandselect_vals[0]); + + /* Defaults for low freq, low rate */ + state->VCAarg = cx24123_AGC_vals[0].VCAprogdata; + state->VGAarg = cx24123_AGC_vals[0].VGAprogdata; + state->bandselectarg = cx24123_bandselect_vals[0].progdata; + vco_div = cx24123_bandselect_vals[0].VCOdivider; + + /* For the given symbol rate, determine the VCA, VGA and FILTUNE programming bits */ + for (i = 0; i < sizeof(cx24123_AGC_vals) / sizeof(cx24123_AGC_vals[0]); i++) + { + if ((cx24123_AGC_vals[i].symbolrate_low <= p->delsys.dvbs.symbol_rate) && + (cx24123_AGC_vals[i].symbolrate_high >= p->delsys.dvbs.symbol_rate) ) { + state->VCAarg = cx24123_AGC_vals[i].VCAprogdata; + state->VGAarg = cx24123_AGC_vals[i].VGAprogdata; + state->FILTune = cx24123_AGC_vals[i].FILTune; + } + } + + /* determine the band to use */ + if(force_band < 1 || force_band > num_bands) + { + for (i = 0; i < num_bands; i++) + { + if ((cx24123_bandselect_vals[i].freq_low <= p->frequency) && + (cx24123_bandselect_vals[i].freq_high >= p->frequency) ) + band = i; + } + } + else + band = force_band - 1; + + state->bandselectarg = cx24123_bandselect_vals[band].progdata; + vco_div = cx24123_bandselect_vals[band].VCOdivider; + + /* determine the charge pump current */ + if ( p->frequency < (cx24123_bandselect_vals[band].freq_low + cx24123_bandselect_vals[band].freq_high)/2 ) + pump = 0x01; + else + pump = 0x02; + + /* Determine the N/A dividers for the requested lband freq (in kHz). */ + /* Note: the reference divider R=10, frequency is in KHz, XTAL is in Hz */ + ndiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) / 32) & 0x1ff; + adiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) % 32) & 0x1f; + + if (adiv == 0) + ndiv++; + + /* control bits 11, refdiv 11, charge pump polarity 1, charge pump current, ndiv, adiv */ + state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) | (pump << 14) | (ndiv << 5) | adiv; + + return 0; +} + /* * Tuner data is 21 bits long, must be left-aligned in data. * Tuner cx24109 is written through a dedicated 3wire interface on the demod chip. */ -static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_parameters *p, u32 data) +//static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_parameters *p, u32 data) +static int cx24123_pll_writereg(struct dvb_frontend* fe, u32 data) { struct cx24123_state *state = fe->demodulator_priv; unsigned long timeout; @@ -626,7 +787,40 @@ static int cx24123_pll_writereg(struct d return 0; } -static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) +static int cx24123_pll_tune_compat(struct dvb_frontend* fe, + struct dvb_frontend_parameters *p) +{ + struct cx24123_state *state = fe->demodulator_priv; + u8 val; + + dprintk("frequency=%i\n", p->frequency); + + if (cx24123_pll_calculate_compat(fe, p) != 0) { + printk("%s: cx24123_pll_calcutate failed\n",__FUNCTION__); + return -EINVAL; + } + + /* Write the new VCO/VGA */ + cx24123_pll_writereg(fe, state->VCAarg); + cx24123_pll_writereg(fe, state->VGAarg); + + /* Write the new bandselect and pll args */ + cx24123_pll_writereg(fe, state->bandselectarg); + cx24123_pll_writereg(fe, state->pllarg); + + /* set the FILTUNE voltage */ + val = cx24123_readreg(state, 0x28) & ~0x3; + cx24123_writereg(state, 0x27, state->FILTune >> 2); + cx24123_writereg(state, 0x28, val | (state->FILTune & 0x3)); + + dprintk("%s: pll tune VCA=%d, band=%d, pll=%d\n",__FUNCTION__,state->VCAarg, + state->bandselectarg,state->pllarg); + + return 0; +} + +static int cx24123_pll_tune(struct dvb_frontend* fe, + struct dvbfe_params *p) { struct cx24123_state *state = fe->demodulator_priv; u8 val; @@ -639,12 +833,12 @@ static int cx24123_pll_tune(struct dvb_f } /* Write the new VCO/VGA */ - cx24123_pll_writereg(fe, p, state->VCAarg); - cx24123_pll_writereg(fe, p, state->VGAarg); + cx24123_pll_writereg(fe, state->VCAarg); + cx24123_pll_writereg(fe, state->VGAarg); /* Write the new bandselect and pll args */ - cx24123_pll_writereg(fe, p, state->bandselectarg); - cx24123_pll_writereg(fe, p, state->pllarg); + cx24123_pll_writereg(fe, state->bandselectarg); + cx24123_pll_writereg(fe, state->pllarg); /* set the FILTUNE voltage */ val = cx24123_readreg(state, 0x28) & ~0x3; @@ -876,9 +1070,9 @@ static int cx24123_set_frontend(struct d state->currentsymbolrate = p->u.qpsk.symbol_rate; cx24123_set_inversion(state, p->inversion); - cx24123_set_fec(state, p->u.qpsk.fec_inner); + cx24123_set_fec_compat(state, p->u.qpsk.fec_inner); cx24123_set_symbolrate(state, p->u.qpsk.symbol_rate); - cx24123_pll_tune(fe, p); + cx24123_pll_tune_compat(fe, p); /* Enable automatic aquisition and reset cycle */ cx24123_writereg(state, 0x03, (cx24123_readreg(state, 0x03) | 0x07)); @@ -898,7 +1092,7 @@ static int cx24123_get_frontend(struct d printk("%s: Failed to get inversion status\n",__FUNCTION__); return -EREMOTEIO; } - if (cx24123_get_fec(state, &p->u.qpsk.fec_inner) != 0) { + if (cx24123_get_fec_compat(state, &p->u.qpsk.fec_inner) != 0) { printk("%s: Failed to get fec status\n",__FUNCTION__); return -EREMOTEIO; } @@ -987,6 +1181,88 @@ error: return NULL; } +static struct dvbfe_info dvbs_info = { + .name = "Conexant CX24123 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_4_5 | + DVBFE_FEC_5_6 | DVBFE_FEC_6_7 | + DVBFE_FEC_7_8 | DVBFE_FEC_AUTO + }, + + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_step = 1011, + .frequency_tolerance = 5000, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000 +}; + +static int cx24123_set_params(struct dvb_frontend* fe, + struct dvbfe_params *p) +{ + struct cx24123_state *state = fe->demodulator_priv; + + dprintk("%s: set_frontend\n",__FUNCTION__); + + if (state->config->set_ts_params) + state->config->set_ts_params(fe, 0); + + state->currentfreq = p->frequency; + state->currentsymbolrate = p->delsys.dvbs.symbol_rate; + + cx24123_set_inversion(state, p->inversion); + cx24123_set_fec(state, p->delsys.dvbs.fec); + cx24123_set_symbolrate(state, p->delsys.dvbs.symbol_rate); + cx24123_pll_tune(fe, p); + + /* Enable automatic aquisition and reset cycle */ + cx24123_writereg(state, 0x03, (cx24123_readreg(state, 0x03) | 0x07)); + cx24123_writereg(state, 0x00, 0x10); + cx24123_writereg(state, 0x00, 0); + + return 0; +} + +static int cx24123_get_params(struct dvb_frontend* fe, + struct dvbfe_params *p) +{ + struct cx24123_state *state = fe->demodulator_priv; + + dprintk("%s: get_frontend\n",__FUNCTION__); + + if (cx24123_get_inversion(state, &p->inversion) != 0) { + printk("%s: Failed to get inversion status\n",__FUNCTION__); + return -EREMOTEIO; + } + if (cx24123_get_fec(state, &p->delsys.dvbs.fec) != 0) { + printk("%s: Failed to get fec status\n",__FUNCTION__); + return -EREMOTEIO; + } + p->frequency = state->currentfreq; + p->delsys.dvbs.symbol_rate = state->currentsymbolrate; + + return 0; +} + +static int cx24123_get_info(struct dvb_frontend *fe, + struct dvbfe_info *fe_info) +{ + memcpy(fe_info, &dvbs_info, sizeof (dvbs_info)); + + return 0; +} + +static int cx24123_get_delsys(struct dvb_frontend *fe, + enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_DVBS; + + return 0; +} + static struct dvb_frontend_ops cx24123_ops = { .info = { @@ -1019,6 +1295,11 @@ static struct dvb_frontend_ops cx24123_o .diseqc_send_burst = cx24123_diseqc_send_burst, .set_tone = cx24123_set_tone, .set_voltage = cx24123_set_voltage, + + .set_params = cx24123_set_params, + .get_params = cx24123_get_params, + .get_info = cx24123_get_info, + .get_delsys = cx24123_get_delsys, }; module_param(debug, int, 0644); diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/dib3000mb.c mp-bc1/linux/drivers/media/dvb/frontends/dib3000mb.c --- v4l-dvb/linux/drivers/media/dvb/frontends/dib3000mb.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/dib3000mb.c 2006-07-17 23:43:50.000000000 +0400 @@ -60,9 +60,10 @@ static int dib3000mb_set_frontend(struct fe_code_rate_t fe_cr = FEC_NONE; int search_state, seq; - if (tuner && fe->ops.tuner_ops.set_params) { - fe->ops.tuner_ops.set_params(fe, fep); - if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + if (tuner && fe->ops.tuner_ops.set_params_compat) { + fe->ops.tuner_ops.set_params_compat(fe, fep); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); deb_setf("bandwidth: "); switch (ofdm->bandwidth) { @@ -730,6 +731,476 @@ error: return NULL; } +static struct dvbfe_info dvbt_info = { + .name = "DiBcom 3000M-B DVB-T", + .delivery = DVBFE_DELSYS_DVBT, + .delsys = { + .dvbt.modulation = DVBFE_MOD_OFDM, + .dvbt.stream_priority = DVBFE_STREAM_PRIORITY_HP | + DVBFE_STREAM_PRIORITY_LP, + }, + + .frequency_min = 44250000, + .frequency_max = 867250000, + .frequency_step = 62500, +}; + +static int dib3000mb_get_info(struct dvb_frontend *fe, + struct dvbfe_info *fe_info) +{ + memcpy(fe_info, &dvbt_info, sizeof (dvbt_info)); + + return 0; +} + +static int dib3000mb_get_delsys(struct dvb_frontend *fe, + enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_DVBT; + + return 0; +} + +static int dib3000mb_get_params(struct dvb_frontend* fe, + struct dvbfe_params *fep) +{ + struct dib3000_state* state = fe->demodulator_priv; + struct dvbt_params *dvbt = &fep->delsys.dvbt; + enum dvbfe_fec *cr; + + u16 tps_val; + int inv_test1,inv_test2; + u32 dds_val, threshold = 0x800000; + + if (!rd(DIB3000MB_REG_TPS_LOCK)) + return 0; + + dds_val = ((rd(DIB3000MB_REG_DDS_VALUE_MSB) & 0xff) << 16) + rd(DIB3000MB_REG_DDS_VALUE_LSB); + deb_getf("DDS_VAL: %x %x %x",dds_val, rd(DIB3000MB_REG_DDS_VALUE_MSB), rd(DIB3000MB_REG_DDS_VALUE_LSB)); + if (dds_val < threshold) + inv_test1 = 0; + else if (dds_val == threshold) + inv_test1 = 1; + else + inv_test1 = 2; + + dds_val = ((rd(DIB3000MB_REG_DDS_FREQ_MSB) & 0xff) << 16) + rd(DIB3000MB_REG_DDS_FREQ_LSB); + deb_getf("DDS_FREQ: %x %x %x",dds_val, rd(DIB3000MB_REG_DDS_FREQ_MSB), rd(DIB3000MB_REG_DDS_FREQ_LSB)); + if (dds_val < threshold) + inv_test2 = 0; + else if (dds_val == threshold) + inv_test2 = 1; + else + inv_test2 = 2; + + fep->inversion = + ((inv_test2 == 2) && (inv_test1==1 || inv_test1==0)) || + ((inv_test2 == 0) && (inv_test1==1 || inv_test1==2)) ? + INVERSION_ON : INVERSION_OFF; + + deb_getf("inversion %d %d, %d\n", inv_test2, inv_test1, fep->inversion); + + switch ((tps_val = rd(DIB3000MB_REG_TPS_QAM))) { + case DIB3000_CONSTELLATION_QPSK: + deb_getf("QPSK "); + dvbt->constellation = DVBFE_MOD_QPSK; + break; + case DIB3000_CONSTELLATION_16QAM: + deb_getf("QAM16 "); + dvbt->constellation = DVBFE_MOD_QAM16; + break; + case DIB3000_CONSTELLATION_64QAM: + deb_getf("QAM64 "); + dvbt->constellation = DVBFE_MOD_QAM64; + break; + default: + err("Unexpected constellation returned by TPS (%d)", tps_val); + break; + } + deb_getf("TPS: %d\n", tps_val); + + if (rd(DIB3000MB_REG_TPS_HRCH)) { + deb_getf("HRCH ON\n"); + cr = &dvbt->code_rate_LP; + dvbt->code_rate_HP = DVBFE_FEC_NONE; + switch ((tps_val = rd(DIB3000MB_REG_TPS_VIT_ALPHA))) { + case DIB3000_ALPHA_0: + deb_getf("HIERARCHY_NONE "); + dvbt->hierarchy = DVBFE_HIERARCHY_OFF; + break; + case DIB3000_ALPHA_1: + deb_getf("HIERARCHY_1 "); + dvbt->hierarchy = DVBFE_HIERARCHY_ON; + dvbt->alpha = DVBFE_ALPHA_1; + break; + case DIB3000_ALPHA_2: + deb_getf("HIERARCHY_2 "); + dvbt->hierarchy = DVBFE_HIERARCHY_ON; + dvbt->alpha = DVBFE_ALPHA_2; + break; + case DIB3000_ALPHA_4: + deb_getf("HIERARCHY_4 "); + dvbt->hierarchy = DVBFE_HIERARCHY_ON; + dvbt->alpha = DVBFE_ALPHA_4; + break; + default: + err("Unexpected ALPHA value returned by TPS (%d)", tps_val); + break; + } + deb_getf("TPS: %d\n", tps_val); + + tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_LP); + } else { + deb_getf("HRCH OFF\n"); + cr = &dvbt->code_rate_HP; + dvbt->code_rate_LP = DVBFE_FEC_NONE; + dvbt->hierarchy = DVBFE_HIERARCHY_OFF; + + tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_HP); + } + + switch (tps_val) { + case DIB3000_FEC_1_2: + deb_getf("FEC_1_2 "); + *cr = DVBFE_FEC_1_2; + break; + case DIB3000_FEC_2_3: + deb_getf("FEC_2_3 "); + *cr = DVBFE_FEC_2_3; + break; + case DIB3000_FEC_3_4: + deb_getf("FEC_3_4 "); + *cr = DVBFE_FEC_3_4; + break; + case DIB3000_FEC_5_6: + deb_getf("FEC_5_6 "); + *cr = DVBFE_FEC_4_5; + break; + case DIB3000_FEC_7_8: + deb_getf("FEC_7_8 "); + *cr = DVBFE_FEC_7_8; + break; + default: + err("Unexpected FEC returned by TPS (%d)", tps_val); + break; + } + deb_getf("TPS: %d\n",tps_val); + + switch ((tps_val = rd(DIB3000MB_REG_TPS_GUARD_TIME))) { + case DIB3000_GUARD_TIME_1_32: + deb_getf("GUARD_INTERVAL_1_32 "); + dvbt->guard_interval = DVBFE_GUARD_INTERVAL_1_32; + break; + case DIB3000_GUARD_TIME_1_16: + deb_getf("GUARD_INTERVAL_1_16 "); + dvbt->guard_interval = DVBFE_GUARD_INTERVAL_1_16; + break; + case DIB3000_GUARD_TIME_1_8: + deb_getf("GUARD_INTERVAL_1_8 "); + dvbt->guard_interval = DVBFE_GUARD_INTERVAL_1_8; + break; + case DIB3000_GUARD_TIME_1_4: + deb_getf("GUARD_INTERVAL_1_4 "); + dvbt->guard_interval = DVBFE_GUARD_INTERVAL_1_4; + break; + default: + err("Unexpected Guard Time returned by TPS (%d)", tps_val); + break; + } + deb_getf("TPS: %d\n", tps_val); + + switch ((tps_val = rd(DIB3000MB_REG_TPS_FFT))) { + case DIB3000_TRANSMISSION_MODE_2K: + deb_getf("TRANSMISSION_MODE_2K "); + dvbt->transmission_mode = DVBFE_TRANSMISSION_MODE_2K; + break; + case DIB3000_TRANSMISSION_MODE_8K: + deb_getf("TRANSMISSION_MODE_8K "); + dvbt->transmission_mode = DVBFE_TRANSMISSION_MODE_8K; + break; + default: + err("unexpected transmission mode return by TPS (%d)", tps_val); + break; + } + deb_getf("TPS: %d\n", tps_val); + + return 0; +} + +static int dib3000mb_set_param(struct dvb_frontend *fe, + struct dvbfe_params *fep, + int tuner) +{ + struct dib3000_state* state = fe->demodulator_priv; + struct dvbt_params *dvbt = &fep->delsys.dvbt; + enum dvbfe_fec fe_cr = DVBFE_FEC_NONE; + int search_state, seq; + + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, fep); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + deb_setf("bandwidth: "); + switch (dvbt->bandwidth) { + case DVBFE_BANDWIDTH_8_MHZ: + deb_setf("8 MHz\n"); + wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[2]); + wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_8mhz); + break; + case DVBFE_BANDWIDTH_7_MHZ: + deb_setf("7 MHz\n"); + wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[1]); + wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_7mhz); + break; + case DVBFE_BANDWIDTH_6_MHZ: + deb_setf("6 MHz\n"); + wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[0]); + wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_6mhz); + break; + case DVBFE_BANDWIDTH_AUTO: + return -EOPNOTSUPP; + default: + err("unkown bandwidth value."); + return -EINVAL; + } + } + wr(DIB3000MB_REG_LOCK1_MASK, DIB3000MB_LOCK1_SEARCH_4); + + deb_setf("transmission mode: "); + switch (dvbt->transmission_mode) { + case DVBFE_TRANSMISSION_MODE_2K: + deb_setf("2k\n"); + wr(DIB3000MB_REG_FFT, DIB3000_TRANSMISSION_MODE_2K); + break; + case DVBFE_TRANSMISSION_MODE_8K: + deb_setf("8k\n"); + wr(DIB3000MB_REG_FFT, DIB3000_TRANSMISSION_MODE_8K); + break; + case DVBFE_TRANSMISSION_MODE_AUTO: + deb_setf("auto\n"); + break; + default: + return -EINVAL; + } + + deb_setf("guard: "); + switch (dvbt->guard_interval) { + case DVBFE_GUARD_INTERVAL_1_32: + deb_setf("1_32\n"); + wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_32); + break; + case DVBFE_GUARD_INTERVAL_1_16: + deb_setf("1_16\n"); + wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_16); + break; + case DVBFE_GUARD_INTERVAL_1_8: + deb_setf("1_8\n"); + wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_8); + break; + case DVBFE_GUARD_INTERVAL_1_4: + deb_setf("1_4\n"); + wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_4); + break; + case DVBFE_GUARD_INTERVAL_AUTO: + deb_setf("auto\n"); + break; + default: + return -EINVAL; + } + + deb_setf("inversion: "); + switch (fep->inversion) { + case INVERSION_OFF: + deb_setf("off\n"); + wr(DIB3000MB_REG_DDS_INV, DIB3000_DDS_INVERSION_OFF); + break; + case INVERSION_AUTO: + deb_setf("auto "); + break; + case INVERSION_ON: + deb_setf("on\n"); + wr(DIB3000MB_REG_DDS_INV, DIB3000_DDS_INVERSION_ON); + break; + default: + return -EINVAL; + } + + deb_setf("constellation: "); + switch (dvbt->constellation) { + case DVBFE_MOD_QPSK: + deb_setf("qpsk\n"); + wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_QPSK); + break; + case DVBFE_MOD_QAM16: + deb_setf("qam16\n"); + wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_16QAM); + break; + case DVBFE_MOD_QAM64: + deb_setf("qam64\n"); + wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_64QAM); + break; + case DVBFE_MOD_QAMAUTO: + break; + default: + return -EINVAL; + } + deb_setf("hierachy: "); + switch (dvbt->hierarchy) { + case DVBFE_HIERARCHY_OFF: + deb_setf("off "); + /* fall through */ + case DVBFE_HIERARCHY_ON: + switch (dvbt->alpha) { + case DVBFE_ALPHA_1: + deb_setf("alpha=1\n"); + wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_1); + break; + case DVBFE_ALPHA_2: + deb_setf("alpha=2\n"); + wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_2); + break; + case DVBFE_ALPHA_4: + deb_setf("alpha=4\n"); + wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_4); + break; + } + break; + case HIERARCHY_AUTO: + deb_setf("alpha=auto\n"); + break; + default: + return -EINVAL; + } + + deb_setf("hierarchy: "); + if (dvbt->hierarchy == DVBFE_HIERARCHY_OFF) { + deb_setf("none\n"); + wr(DIB3000MB_REG_VIT_HRCH, DIB3000_HRCH_OFF); + wr(DIB3000MB_REG_VIT_HP, DIB3000_SELECT_HP); + fe_cr = dvbt->code_rate_HP; + } else if (dvbt->hierarchy != DVBFE_HIERARCHY_AUTO) { + deb_setf("on\n"); + wr(DIB3000MB_REG_VIT_HRCH, DIB3000_HRCH_ON); + wr(DIB3000MB_REG_VIT_HP, DIB3000_SELECT_LP); + fe_cr = dvbt->code_rate_LP; + } + deb_setf("fec: "); + switch (fe_cr) { + case DVBFE_FEC_1_2: + deb_setf("1_2\n"); + wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_1_2); + break; + case DVBFE_FEC_2_3: + deb_setf("2_3\n"); + wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_2_3); + break; + case DVBFE_FEC_3_4: + deb_setf("3_4\n"); + wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_3_4); + break; + case DVBFE_FEC_5_6: + deb_setf("5_6\n"); + wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_5_6); + break; + case DVBFE_FEC_7_8: + deb_setf("7_8\n"); + wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_7_8); + break; + case DVBFE_FEC_NONE: + deb_setf("none "); + break; + case DVBFE_FEC_AUTO: + deb_setf("auto\n"); + break; + default: + return -EINVAL; + } + + seq = dib3000_seq + [dvbt->transmission_mode == DVBFE_TRANSMISSION_MODE_AUTO] + [dvbt->guard_interval == DVBFE_GUARD_INTERVAL_AUTO] + [fep->inversion == INVERSION_AUTO]; + + deb_setf("seq? %d\n", seq); + + wr(DIB3000MB_REG_SEQ, seq); + + wr(DIB3000MB_REG_ISI, seq ? DIB3000MB_ISI_INHIBIT : DIB3000MB_ISI_ACTIVATE); + + if (dvbt->transmission_mode == TRANSMISSION_MODE_2K) { + if (dvbt->guard_interval == GUARD_INTERVAL_1_8) { + wr(DIB3000MB_REG_SYNC_IMPROVEMENT, DIB3000MB_SYNC_IMPROVE_2K_1_8); + } else { + wr(DIB3000MB_REG_SYNC_IMPROVEMENT, DIB3000MB_SYNC_IMPROVE_DEFAULT); + } + + wr(DIB3000MB_REG_UNK_121, DIB3000MB_UNK_121_2K); + } else { + wr(DIB3000MB_REG_UNK_121, DIB3000MB_UNK_121_DEFAULT); + } + + wr(DIB3000MB_REG_MOBILE_ALGO, DIB3000MB_MOBILE_ALGO_OFF); + wr(DIB3000MB_REG_MOBILE_MODE_QAM, DIB3000MB_MOBILE_MODE_QAM_OFF); + wr(DIB3000MB_REG_MOBILE_MODE, DIB3000MB_MOBILE_MODE_OFF); + + wr_foreach(dib3000mb_reg_agc_bandwidth, dib3000mb_agc_bandwidth_high); + + wr(DIB3000MB_REG_ISI, DIB3000MB_ISI_ACTIVATE); + + wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_AGC + DIB3000MB_RESTART_CTRL); + wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_OFF); + + /* wait for AGC lock */ + msleep(70); + + wr_foreach(dib3000mb_reg_agc_bandwidth, dib3000mb_agc_bandwidth_low); + + /* something has to be auto searched */ + if (dvbt->constellation == DVBFE_MOD_QAMAUTO || + dvbt->hierarchy == DVBFE_HIERARCHY_AUTO || + fe_cr == DVBFE_FEC_AUTO || + fep->inversion == INVERSION_AUTO) { + int as_count=0; + + deb_setf("autosearch enabled.\n"); + + wr(DIB3000MB_REG_ISI, DIB3000MB_ISI_INHIBIT); + + wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_AUTO_SEARCH); + wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_OFF); + + while ((search_state = + dib3000_search_status( + rd(DIB3000MB_REG_AS_IRQ_PENDING), + rd(DIB3000MB_REG_LOCK2_VALUE))) < 0 && as_count++ < 100) + msleep(1); + + deb_setf("search_state after autosearch %d after %d checks\n",search_state,as_count); + + if (search_state == 1) { + struct dvbfe_params feps; + if (dib3000mb_get_params(fe, &feps) == 0) { + deb_setf("reading tuning data from frontend succeeded.\n"); + return dib3000mb_set_param(fe, &feps, 0); + } + } + + } else { + wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_CTRL); + wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_OFF); + } + + return 0; +} + +static int dib3000mb_set_params(struct dvb_frontend* fe, + struct dvbfe_params *fep) +{ + + return dib3000mb_set_param(fe, fep, 1); +} + static struct dvb_frontend_ops dib3000mb_ops = { .info = { @@ -762,6 +1233,11 @@ static struct dvb_frontend_ops dib3000mb .read_signal_strength = dib3000mb_read_signal_strength, .read_snr = dib3000mb_read_snr, .read_ucblocks = dib3000mb_read_unc_blocks, + + .set_params = dib3000mb_set_params, + .get_params = dib3000mb_get_params, + .get_info = dib3000mb_get_info, + .get_delsys = dib3000mb_get_delsys, }; MODULE_AUTHOR(DRIVER_AUTHOR); diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/dvb_dummy_fe.c mp-bc1/linux/drivers/media/dvb/frontends/dvb_dummy_fe.c --- v4l-dvb/linux/drivers/media/dvb/frontends/dvb_dummy_fe.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/dvb_dummy_fe.c 2006-07-05 01:11:07.000000000 +0400 @@ -76,9 +76,10 @@ static int dvb_dummy_fe_get_frontend(str static int dvb_dummy_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { - 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); } return 0; diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/dvb-pll.c mp-bc1/linux/drivers/media/dvb/frontends/dvb-pll.c --- v4l-dvb/linux/drivers/media/dvb/frontends/dvb-pll.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/dvb-pll.c 2006-07-17 23:44:04.000000000 +0400 @@ -514,7 +514,7 @@ static int dvb_pll_sleep(struct dvb_fron return 0; } -static int dvb_pll_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +static int dvb_pll_set_params_compat(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { struct dvb_pll_priv *priv = fe->tuner_priv; u8 buf[4]; @@ -555,7 +555,7 @@ static int dvb_pll_set_params(struct dvb return 0; } -static int dvb_pll_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8 *buf, int buf_len) +static int dvb_pll_calc_regs_compat(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8 *buf, int buf_len) { struct dvb_pll_priv *priv = fe->tuner_priv; int result; @@ -605,8 +605,8 @@ static int dvb_pll_get_bandwidth(struct static struct dvb_tuner_ops dvb_pll_tuner_ops = { .release = dvb_pll_release, .sleep = dvb_pll_sleep, - .set_params = dvb_pll_set_params, - .calc_regs = dvb_pll_calc_regs, + .set_params_compat = dvb_pll_set_params_compat, + .calc_regs_compat = dvb_pll_calc_regs_compat, .get_frequency = dvb_pll_get_frequency, .get_bandwidth = dvb_pll_get_bandwidth, }; diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/l64781.c mp-bc1/linux/drivers/media/dvb/frontends/l64781.c --- v4l-dvb/linux/drivers/media/dvb/frontends/l64781.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/l64781.c 2006-07-17 23:44:12.000000000 +0400 @@ -140,9 +140,10 @@ static int apply_frontend_param (struct u8 val0x06; int bw = p->bandwidth - BANDWIDTH_8_MHZ; - if (fe->ops.tuner_ops.set_params) { - fe->ops.tuner_ops.set_params(fe, param); - 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, param); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); } if (param->inversion != INVERSION_ON && @@ -564,6 +565,32 @@ error: return NULL; } +static struct dvbfe_info dvbt_info = { + .name = "LSI L64781 DVB-T", + .delivery = DVBFE_DELSYS_DVBT, + .delsys = { + .dvbt.modulation = DVBFE_MOD_OFDM, + .dvbt.stream_priority = DVBFE_STREAM_PRIORITY_HP | + DVBFE_STREAM_PRIORITY_LP, + }, + + .frequency_step = 166666, +}; + +static int l64781_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info) +{ + memcpy(fe_info, &dvbt_info, sizeof (dvbt_info)); + + return 0; +} + +static int l64781_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_DVBT; + + return 0; +} + static struct dvb_frontend_ops l64781_ops = { .info = { @@ -594,6 +621,11 @@ static struct dvb_frontend_ops l64781_op .read_signal_strength = l64781_read_signal_strength, .read_snr = l64781_read_snr, .read_ucblocks = l64781_read_ucblocks, + +// .set_params = l64781_set_params, +// .get_params = l64781_get_params, + .get_info = l64781_get_info, + .get_delsys = l64781_get_delsys, }; MODULE_DESCRIPTION("LSI L64781 DVB-T Demodulator driver"); diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/lgdt330x.c mp-bc1/linux/drivers/media/dvb/frontends/lgdt330x.c --- v4l-dvb/linux/drivers/media/dvb/frontends/lgdt330x.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/lgdt330x.c 2006-07-17 23:44:19.000000000 +0400 @@ -399,9 +399,134 @@ static int lgdt330x_set_parameters(struc } /* Tune to the specified frequency */ + if (fe->ops.tuner_ops.set_params_compat) { + fe->ops.tuner_ops.set_params_compat(fe, param); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + } + + /* Keep track of the new frequency */ + /* FIXME this is the wrong way to do this... */ + /* The tuner is shared with the video4linux analog API */ + state->current_frequency = param->frequency; + + lgdt330x_SwReset(state); + return 0; +} + +static int lgdt330x_set_params(struct dvb_frontend* fe, + struct dvbfe_params *param) +{ + /* + * Array of byte pairs + * to initialize 8VSB for lgdt3303 chip 50 MHz IF + */ + static u8 lgdt3303_8vsb_44_data[] = { + 0x04, 0x00, + 0x0d, 0x40, + 0x0e, 0x87, + 0x0f, 0x8e, + 0x10, 0x01, + 0x47, 0x8b + }; + + /* + * Array of byte pairs + * to initialize QAM for lgdt3303 chip + */ + static u8 lgdt3303_qam_data[] = { + 0x04, 0x00, + 0x0d, 0x00, + 0x0e, 0x00, + 0x0f, 0x00, + 0x10, 0x00, + 0x51, 0x63, + 0x47, 0x66, + 0x48, 0x66, + 0x4d, 0x1a, + 0x49, 0x08, + 0x4a, 0x9b + }; + + struct lgdt330x_state* state = fe->demodulator_priv; + + static u8 top_ctrl_cfg[] = { TOP_CONTROL, 0x03 }; + + int err; + /* Change only if we are actually changing the modulation */ + if (state->current_modulation != param->delsys.atsc.modulation) { + switch(param->delsys.atsc.modulation) { + case DVBFE_MOD_VSB8: + dprintk("%s: 8VSB MODE\n", __FUNCTION__); + + /* Select VSB mode */ + top_ctrl_cfg[1] = 0x03; + + /* Select ANT connector if supported by card */ + if (state->config->pll_rf_set) + state->config->pll_rf_set(fe, 1); + + if (state->config->demod_chip == LGDT3303) { + err = i2c_write_demod_bytes(state, lgdt3303_8vsb_44_data, + sizeof (lgdt3303_8vsb_44_data)); + } + break; + + case DVBFE_MOD_QAM64: + dprintk("%s: QAM64 MODE\n", __FUNCTION__); + + /* Select QAM_64 mode */ + top_ctrl_cfg[1] = 0x00; + + /* Select CABLE connector if supported by card */ + if (state->config->pll_rf_set) + state->config->pll_rf_set(fe, 0); + + if (state->config->demod_chip == LGDT3303) { + err = i2c_write_demod_bytes(state, lgdt3303_qam_data, + sizeof(lgdt3303_qam_data)); + } + break; + + case DVBFE_MOD_QAM256: + dprintk("%s: QAM_256 MODE\n", __FUNCTION__); + + /* Select QAM_256 mode */ + top_ctrl_cfg[1] = 0x01; + + /* Select CABLE connector if supported by card */ + if (state->config->pll_rf_set) + state->config->pll_rf_set(fe, 0); + + if (state->config->demod_chip == LGDT3303) { + err = i2c_write_demod_bytes(state, lgdt3303_qam_data, + sizeof(lgdt3303_qam_data)); + } + break; + default: + printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __FUNCTION__, param->delsys.atsc.modulation); + return -1; + } + /* + * select serial or parallel MPEG harware interface + * Serial: 0x04 for LGDT3302 or 0x40 for LGDT3303 + * Parallel: 0x00 + */ + top_ctrl_cfg[1] |= state->config->serial_mpeg; + + /* Select the requested mode */ + i2c_write_demod_bytes(state, top_ctrl_cfg, + sizeof(top_ctrl_cfg)); + if (state->config->set_ts_params) + state->config->set_ts_params(fe, 0); + state->current_modulation = param->delsys.atsc.modulation; + } + + /* Tune to the specified frequency */ if (fe->ops.tuner_ops.set_params) { fe->ops.tuner_ops.set_params(fe, param); - if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); } /* Keep track of the new frequency */ @@ -421,6 +546,14 @@ static int lgdt330x_get_frontend(struct return 0; } +static int lgdt330x_get_params(struct dvb_frontend* fe, + struct dvbfe_params* param) +{ + struct lgdt330x_state *state = fe->demodulator_priv; + param->frequency = state->current_frequency; + return 0; +} + static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status) { struct lgdt330x_state* state = fe->demodulator_priv; @@ -769,6 +902,60 @@ error: return NULL; } +static struct dvbfe_info lgdt3302_info = { + .name = "LG LGDT3302 ATSC", + .delivery = DVBFE_DELSYS_ATSC, + .delsys = { + .atsc.modulation = DVBFE_MOD_VSB8 | DVBFE_MOD_QAM64 | + DVBFE_MOD_QAM256 + }, + + .frequency_min = 54000000, + .frequency_max = 858000000, + .frequency_step = 62500, + .symbol_rate_min = 5056941, + .symbol_rate_max = 10762000 +}; + +static struct dvbfe_info lgdt3303_info = { + .name = "LG LGDT3302 ATSC", + .delivery = DVBFE_DELSYS_ATSC, + .delsys = { + .atsc.modulation = DVBFE_MOD_VSB8 | DVBFE_MOD_QAM64 | + DVBFE_MOD_QAM256 + }, + + .frequency_min = 54000000, + .frequency_max = 858000000, + .frequency_step = 62500, + .symbol_rate_min = 5056941, + .symbol_rate_max = 10762000 +}; + +static int lgdt330x_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info) +{ + struct lgdt330x_state *state = fe->demodulator_priv; + + switch(state->config->demod_chip) { + case LGDT3302: + memcpy(fe_info, &lgdt3302_info, sizeof (lgdt3302_info)); + break; + case LGDT3303: + memcpy(fe_info, &lgdt3303_info, sizeof (lgdt3303_info)); + break; + default: + break; + } + return 0; +} + +static int lgdt330x_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_DVBS; + + return 0; +} + static struct dvb_frontend_ops lgdt3302_ops = { .info = { .name= "LG Electronics LGDT3302 VSB/QAM Frontend", @@ -790,6 +977,11 @@ static struct dvb_frontend_ops lgdt3302_ .read_snr = lgdt3302_read_snr, .read_ucblocks = lgdt330x_read_ucblocks, .release = lgdt330x_release, + + .set_params = lgdt330x_set_params, + .get_params = lgdt330x_get_params, + .get_info = lgdt330x_get_info, + .get_delsys = lgdt330x_get_delsys, }; static struct dvb_frontend_ops lgdt3303_ops = { @@ -813,6 +1005,11 @@ static struct dvb_frontend_ops lgdt3303_ .read_snr = lgdt3303_read_snr, .read_ucblocks = lgdt330x_read_ucblocks, .release = lgdt330x_release, + + .set_params = lgdt330x_set_params, + .get_params = lgdt330x_get_params, + .get_info = lgdt330x_get_info, + .get_delsys = lgdt330x_get_delsys, }; MODULE_DESCRIPTION("LGDT330X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver"); diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/lg_h06xf.h mp-bc1/linux/drivers/media/dvb/frontends/lg_h06xf.h --- v4l-dvb/linux/drivers/media/dvb/frontends/lg_h06xf.h 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/lg_h06xf.h 2006-07-08 00:39:48.000000000 +0400 @@ -20,8 +20,9 @@ #define _LG_H06XF_H_ #include "dvb-pll.h" -static int lg_h06xf_pll_set(struct dvb_frontend* fe, struct i2c_adapter* i2c_adap, - struct dvb_frontend_parameters* params) +static int lg_h06xf_pll_set(struct dvb_frontend* fe, + struct i2c_adapter* i2c_adap, + struct dvbfe_params* params) { u8 buf[4]; struct i2c_msg msg = { .addr = 0x61, .flags = 0, @@ -67,4 +68,54 @@ static int lg_h06xf_pll_set(struct dvb_f return 0; } + +static int lg_h06xf_pll_set_compat(struct dvb_frontend* fe, + struct i2c_adapter* i2c_adap, + struct dvb_frontend_parameters* params) +{ + u8 buf[4]; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, + .buf = buf, .len = sizeof(buf) }; + int err; + + dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf, params->frequency, 0); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) { + printk(KERN_WARNING "lg_h06xf: %s error " + "(addr %02x <- %02x, err = %i)\n", + __FUNCTION__, buf[0], buf[1], err); + if (err < 0) + return err; + else + return -EREMOTEIO; + } + + /* Set the Auxiliary Byte. */ +#if 0 + buf[2] &= ~0x20; + buf[2] |= 0x18; + buf[3] = 0x50; +#else + buf[0] = buf[2]; + buf[0] &= ~0x20; + buf[0] |= 0x18; + buf[1] = 0x50; + msg.len = 2; #endif + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) { + printk(KERN_WARNING "lg_h06xf: %s error " + "(addr %02x <- %02x, err = %i)\n", + __FUNCTION__, buf[0], buf[1], err); + if (err < 0) + return err; + else + return -EREMOTEIO; + } + + return 0; +} + +#endif // _LG_H06XF_H_ diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/mt312.c mp-bc1/linux/drivers/media/dvb/frontends/mt312.c --- 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-17 23:44:26.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,195 @@ 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 struct dvb_frontend_ops vp310_mt312_ops = { .info = { @@ -654,6 +868,11 @@ 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, }; struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config, diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/mt352.c mp-bc1/linux/drivers/media/dvb/frontends/mt352.c --- v4l-dvb/linux/drivers/media/dvb/frontends/mt352.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/mt352.c 2006-07-17 23:44:29.000000000 +0400 @@ -287,8 +287,8 @@ static int mt352_set_parameters(struct d mt352_calc_input_freq(state, buf+6); if (state->config.no_tuner) { - if (fe->ops.tuner_ops.set_params) { - fe->ops.tuner_ops.set_params(fe, param); + if (fe->ops.tuner_ops.set_params_compat) { + fe->ops.tuner_ops.set_params_compat(fe, param); if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); } @@ -296,8 +296,8 @@ static int mt352_set_parameters(struct d mt352_write(fe, buf, 8); mt352_write(fe, fsm_go, 2); } else { - if (fe->ops.tuner_ops.calc_regs) { - fe->ops.tuner_ops.calc_regs(fe, param, buf+8, 5); + if (fe->ops.tuner_ops.calc_regs_compat) { + fe->ops.tuner_ops.calc_regs_compat(fe, param, buf+8, 5); buf[8] <<= 1; mt352_write(fe, buf, sizeof(buf)); mt352_write(fe, tuner_go, 2); @@ -563,6 +563,289 @@ error: return NULL; } +static struct dvbfe_info dvbt_info = { + .name = "Zarlink MT352 DVB-T", + .delivery = DVBFE_DELSYS_DVBT, + .delsys = { + .dvbt.modulation = DVBFE_MOD_OFDM, + .dvbt.stream_priority = DVBFE_STREAM_PRIORITY_HP | + DVBFE_STREAM_PRIORITY_LP, + }, + + .frequency_min = 177000000, + .frequency_max = 858000000, + .frequency_step = 166666, +}; + +static int mt352_set_params(struct dvb_frontend* fe, + struct dvbfe_params *param) +{ + struct mt352_state* state = fe->demodulator_priv; + unsigned char buf[13]; + static unsigned char tuner_go[] = { 0x5d, 0x01 }; + static unsigned char fsm_go[] = { 0x5e, 0x01 }; + unsigned int tps = 0; + struct dvbt_params *op = ¶m->delsys.dvbt; + + switch (op->code_rate_HP) { + case DVBFE_FEC_2_3: + tps |= (1 << 7); + break; + case DVBFE_FEC_3_4: + tps |= (2 << 7); + break; + case DVBFE_FEC_5_6: + tps |= (3 << 7); + break; + case DVBFE_FEC_7_8: + tps |= (4 << 7); + break; + case DVBFE_FEC_1_2: + case DVBFE_FEC_AUTO: + break; + default: + return -EINVAL; + } + + switch (op->code_rate_LP) { + case DVBFE_FEC_2_3: + tps |= (1 << 4); + break; + case DVBFE_FEC_3_4: + tps |= (2 << 4); + break; + case DVBFE_FEC_5_6: + tps |= (3 << 4); + break; + case DVBFE_FEC_7_8: + tps |= (4 << 4); + break; + case DVBFE_FEC_1_2: + case DVBFE_FEC_AUTO: + break; + case DVBFE_FEC_NONE: + if (op->hierarchy == DVBFE_HIERARCHY_AUTO || + op->hierarchy == DVBFE_HIERARCHY_OFF) + break; + default: + return -EINVAL; + } + + switch (op->constellation) { + case DVBFE_MOD_QPSK: + break; + case DVBFE_MOD_QAMAUTO: + case DVBFE_MOD_QAM16: + tps |= (1 << 13); + break; + case DVBFE_MOD_QAM64: + tps |= (2 << 13); + break; + default: + return -EINVAL; + } + + switch (op->transmission_mode) { + case DVBFE_TRANSMISSION_MODE_2K: + case DVBFE_TRANSMISSION_MODE_AUTO: + break; + case DVBFE_TRANSMISSION_MODE_8K: + tps |= (1 << 0); + break; + default: + return -EINVAL; + } + + switch (op->guard_interval) { + case DVBFE_GUARD_INTERVAL_1_32: + case DVBFE_GUARD_INTERVAL_AUTO: + break; + case DVBFE_GUARD_INTERVAL_1_16: + tps |= (1 << 2); + break; + case DVBFE_GUARD_INTERVAL_1_8: + tps |= (2 << 2); + break; + case DVBFE_GUARD_INTERVAL_1_4: + tps |= (3 << 2); + break; + default: + return -EINVAL; + } + + switch (op->hierarchy) { + case DVBFE_HIERARCHY_AUTO: + case DVBFE_HIERARCHY_OFF: + break; + case DVBFE_HIERARCHY_ON: + switch (op->alpha) { + case DVBFE_ALPHA_1: + tps |= (1 << 10); + break; + case DVBFE_ALPHA_2: + tps |= (2 << 10); + break; + case DVBFE_ALPHA_4: + tps |= (3 << 10); + break; + } + break; + default: + return -EINVAL; + } + + buf[0] = TPS_GIVEN_1; /* TPS_GIVEN_1 and following registers */ + + buf[1] = msb(tps); /* TPS_GIVEN_(1|0) */ + buf[2] = lsb(tps); + + buf[3] = 0x50; // old +// buf[3] = 0xf4; // pinnacle + + mt352_calc_nominal_rate(state, op->bandwidth, buf+4); + mt352_calc_input_freq(state, buf+6); + + if (state->config.no_tuner) { + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, param); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + } + + mt352_write(fe, buf, 8); + mt352_write(fe, fsm_go, 2); + } else { + if (fe->ops.tuner_ops.calc_regs) { + fe->ops.tuner_ops.calc_regs(fe, param, buf+8, 5); + buf[8] <<= 1; + mt352_write(fe, buf, sizeof (buf)); + mt352_write(fe, tuner_go, 2); + } + } + + return 0; +} + +static int mt352_get_params(struct dvb_frontend* fe, + struct dvbfe_params *param) +{ + struct mt352_state* state = fe->demodulator_priv; + u16 tps; + u16 div; + u8 trl; + struct dvbt_params *op = ¶m->delsys.dvbt; + enum dvbfe_fec tps_fec_to_api[8] = { + DVBFE_FEC_1_2, + DVBFE_FEC_2_3, + DVBFE_FEC_3_4, + DVBFE_FEC_5_6, + DVBFE_FEC_7_8, + DVBFE_FEC_AUTO, + DVBFE_FEC_AUTO, + DVBFE_FEC_AUTO + }; + + if ( (mt352_read_register(state,0x00) & 0xC0) != 0xC0 ) + return -EINVAL; + + /* Use TPS_RECEIVED-registers, not the TPS_CURRENT-registers because + * the mt352 sometimes works with the wrong parameters + */ + tps = (mt352_read_register(state, TPS_RECEIVED_1) << 8) | mt352_read_register(state, TPS_RECEIVED_0); + div = (mt352_read_register(state, CHAN_START_1) << 8) | mt352_read_register(state, CHAN_START_0); + trl = mt352_read_register(state, TRL_NOMINAL_RATE_1); + + op->code_rate_HP = tps_fec_to_api[(tps >> 7) & 7]; + op->code_rate_LP = tps_fec_to_api[(tps >> 4) & 7]; + + switch ( (tps >> 13) & 3) { + case 0: + op->constellation = DVBFE_MOD_QPSK; + break; + case 1: + op->constellation = DVBFE_MOD_QAM16; + break; + case 2: + op->constellation = DVBFE_MOD_QAM64; + break; + default: + op->constellation = DVBFE_MOD_QAMAUTO; + break; + } + + op->transmission_mode = (tps & 0x01) ? DVBFE_TRANSMISSION_MODE_8K : DVBFE_TRANSMISSION_MODE_2K; + + switch ((tps >> 2) & 3) { + case 0: + op->guard_interval = DVBFE_GUARD_INTERVAL_1_32; + break; + case 1: + op->guard_interval = DVBFE_GUARD_INTERVAL_1_16; + break; + case 2: + op->guard_interval = DVBFE_GUARD_INTERVAL_1_8; + break; + case 3: + op->guard_interval = DVBFE_GUARD_INTERVAL_1_4; + break; + default: + op->guard_interval = DVBFE_GUARD_INTERVAL_AUTO; + break; + } + + switch ((tps >> 10) & 7) { + case 0: + op->hierarchy = DVBFE_HIERARCHY_OFF; + break; + case 1: + op->alpha = DVBFE_ALPHA_1; + op->hierarchy = DVBFE_HIERARCHY_ON; + break; + case 2: + op->alpha = DVBFE_ALPHA_2; + op->hierarchy = DVBFE_HIERARCHY_ON; + break; + case 3: + op->alpha = DVBFE_ALPHA_4; + op->hierarchy = DVBFE_HIERARCHY_ON; + break; + default: + op->hierarchy = DVBFE_HIERARCHY_AUTO; + break; + } + + param->frequency = (500 * (div - IF_FREQUENCYx6) ) / 3 * 1000; + + if (trl == 0x72) + op->bandwidth = DVBFE_BANDWIDTH_8_MHZ; + else if (trl == 0x64) + op->bandwidth = DVBFE_BANDWIDTH_7_MHZ; + else + op->bandwidth = DVBFE_BANDWIDTH_6_MHZ; + + + if (mt352_read_register(state, STATUS_2) & 0x02) + param->inversion = INVERSION_OFF; + else + param->inversion = INVERSION_ON; + + return 0; +} + +static int mt352_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info) +{ + memcpy(fe_info, &dvbt_info, sizeof (dvbt_info)); + + return 0; +} + +static int mt352_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_DVBT; + + return 0; +} + static struct dvb_frontend_ops mt352_ops = { .info = { @@ -595,6 +878,11 @@ static struct dvb_frontend_ops mt352_ops .read_signal_strength = mt352_read_signal_strength, .read_snr = mt352_read_snr, .read_ucblocks = mt352_read_ucblocks, + + .set_params = mt352_set_params, + .get_params = mt352_get_params, + .get_info = mt352_get_info, + .get_delsys = mt352_get_delsys, }; module_param(debug, int, 0644); diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/nxt200x.c mp-bc1/linux/drivers/media/dvb/frontends/nxt200x.c --- v4l-dvb/linux/drivers/media/dvb/frontends/nxt200x.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/nxt200x.c 2006-07-17 23:44:37.000000000 +0400 @@ -547,8 +547,8 @@ static int nxt200x_setup_frontend_parame } /* get tuning information */ - if (fe->ops.tuner_ops.calc_regs) { - fe->ops.tuner_ops.calc_regs(fe, p, buf, 5); + if (fe->ops.tuner_ops.calc_regs_compat) { + fe->ops.tuner_ops.calc_regs_compat(fe, p, buf, 5); } /* set additional params */ @@ -1209,6 +1209,309 @@ error: return NULL; } +static struct dvbfe_info nxt2002_info = { + .name = "Nextwave NXT2002 ATSC", + .delivery = DVBFE_DELSYS_ATSC, + .delsys = { + .atsc.modulation = DVBFE_MOD_VSB8 | DVBFE_MOD_QAM64 | + DVBFE_MOD_QAM256 + }, + + .frequency_min = 54000000, + .frequency_max = 860000000, + .frequency_step = 166666, +}; + +static struct dvbfe_info nxt2004_info = { + .name = "Nextwave NXT2004 ATSC", + .delivery = DVBFE_DELSYS_ATSC, + .delsys = { + .atsc.modulation = DVBFE_MOD_VSB8 | DVBFE_MOD_QAM64 | + DVBFE_MOD_QAM256 + }, + + .frequency_min = 54000000, + .frequency_max = 860000000, + .frequency_step = 166666, +}; + +static int nxt200x_set_params(struct dvb_frontend* fe, + struct dvbfe_params *p) +{ + struct nxt200x_state* state = fe->demodulator_priv; + u8 buf[5]; + + /* stop the micro first */ + nxt200x_microcontroller_stop(state); + + if (state->demod_chip == NXT2004) { + /* make sure demod is set to digital */ + buf[0] = 0x04; + nxt200x_writebytes(state, 0x14, buf, 1); + buf[0] = 0x00; + nxt200x_writebytes(state, 0x17, buf, 1); + } + + /* get tuning information */ + if (fe->ops.tuner_ops.calc_regs) { + fe->ops.tuner_ops.calc_regs(fe, p, buf, 5); + } + + /* set additional params */ + switch (p->delsys.atsc.modulation) { + case DVBFE_MOD_QAM64: + case DVBFE_MOD_QAM256: + /* Set punctured clock for QAM */ + /* This is just a guess since I am unable to test it */ + if (state->config->set_ts_params) + state->config->set_ts_params(fe, 1); + + /* set input */ + if (state->config->set_pll_input) + state->config->set_pll_input(buf, 1); + break; + case DVBFE_MOD_VSB8: + /* Set non-punctured clock for VSB */ + if (state->config->set_ts_params) + state->config->set_ts_params(fe, 0); + + /* set input */ + if (state->config->set_pll_input) + state->config->set_pll_input(buf, 0); + break; + default: + return -EINVAL; + break; + } + + /* write frequency information */ + nxt200x_writetuner(state, buf); + + /* reset the agc now that tuning has been completed */ + nxt200x_agc_reset(state); + + /* set target power level */ + switch (p->delsys.atsc.modulation) { + case DVBFE_MOD_QAM64: + case DVBFE_MOD_QAM256: + buf[0] = 0x74; + break; + case DVBFE_MOD_VSB8: + buf[0] = 0x70; + break; + default: + return -EINVAL; + break; + } + nxt200x_writebytes(state, 0x42, buf, 1); + + /* configure sdm */ + switch (state->demod_chip) { + case NXT2002: + buf[0] = 0x87; + break; + case NXT2004: + buf[0] = 0x07; + break; + default: + return -EINVAL; + break; + } + nxt200x_writebytes(state, 0x57, buf, 1); + + /* write sdm1 input */ + buf[0] = 0x10; + buf[1] = 0x00; + switch (state->demod_chip) { + case NXT2002: + nxt200x_writereg_multibyte(state, 0x58, buf, 2); + break; + case NXT2004: + nxt200x_writebytes(state, 0x58, buf, 2); + break; + default: + return -EINVAL; + break; + } + + /* write sdmx input */ + switch (p->delsys.atsc.modulation) { + case DVBFE_MOD_QAM64: + buf[0] = 0x68; + break; + case DVBFE_MOD_QAM256: + buf[0] = 0x64; + break; + case DVBFE_MOD_VSB8: + buf[0] = 0x60; + break; + default: + return -EINVAL; + break; + } + buf[1] = 0x00; + switch (state->demod_chip) { + case NXT2002: + nxt200x_writereg_multibyte(state, 0x5C, buf, 2); + break; + case NXT2004: + nxt200x_writebytes(state, 0x5C, buf, 2); + break; + default: + return -EINVAL; + break; + } + + /* write adc power lpf fc */ + buf[0] = 0x05; + nxt200x_writebytes(state, 0x43, buf, 1); + + if (state->demod_chip == NXT2004) { + /* write ??? */ + buf[0] = 0x00; + buf[1] = 0x00; + nxt200x_writebytes(state, 0x46, buf, 2); + } + + /* write accumulator2 input */ + buf[0] = 0x80; + buf[1] = 0x00; + switch (state->demod_chip) { + case NXT2002: + nxt200x_writereg_multibyte(state, 0x4B, buf, 2); + break; + case NXT2004: + nxt200x_writebytes(state, 0x4B, buf, 2); + break; + default: + return -EINVAL; + break; + } + + /* write kg1 */ + buf[0] = 0x00; + nxt200x_writebytes(state, 0x4D, buf, 1); + + /* write sdm12 lpf fc */ + buf[0] = 0x44; + nxt200x_writebytes(state, 0x55, buf, 1); + + /* write agc control reg */ + buf[0] = 0x04; + nxt200x_writebytes(state, 0x41, buf, 1); + + if (state->demod_chip == NXT2004) { + nxt200x_readreg_multibyte(state, 0x80, buf, 1); + buf[0] = 0x24; + nxt200x_writereg_multibyte(state, 0x80, buf, 1); + + /* soft reset? */ + nxt200x_readreg_multibyte(state, 0x08, buf, 1); + buf[0] = 0x10; + nxt200x_writereg_multibyte(state, 0x08, buf, 1); + nxt200x_readreg_multibyte(state, 0x08, buf, 1); + buf[0] = 0x00; + nxt200x_writereg_multibyte(state, 0x08, buf, 1); + + nxt200x_readreg_multibyte(state, 0x80, buf, 1); + buf[0] = 0x04; + nxt200x_writereg_multibyte(state, 0x80, buf, 1); + buf[0] = 0x00; + nxt200x_writereg_multibyte(state, 0x81, buf, 1); + buf[0] = 0x80; buf[1] = 0x00; buf[2] = 0x00; + nxt200x_writereg_multibyte(state, 0x82, buf, 3); + nxt200x_readreg_multibyte(state, 0x88, buf, 1); + buf[0] = 0x11; + nxt200x_writereg_multibyte(state, 0x88, buf, 1); + nxt200x_readreg_multibyte(state, 0x80, buf, 1); + buf[0] = 0x44; + nxt200x_writereg_multibyte(state, 0x80, buf, 1); + } + + /* write agc ucgp0 */ + switch (p->delsys.atsc.modulation) { + case DVBFE_MOD_QAM64: + buf[0] = 0x02; + break; + case DVBFE_MOD_QAM256: + buf[0] = 0x03; + break; + case DVBFE_MOD_VSB8: + buf[0] = 0x00; + break; + default: + return -EINVAL; + break; + } + nxt200x_writebytes(state, 0x30, buf, 1); + + /* write agc control reg */ + buf[0] = 0x00; + nxt200x_writebytes(state, 0x41, buf, 1); + + /* write accumulator2 input */ + buf[0] = 0x80; + buf[1] = 0x00; + switch (state->demod_chip) { + case NXT2002: + nxt200x_writereg_multibyte(state, 0x49, buf, 2); + nxt200x_writereg_multibyte(state, 0x4B, buf, 2); + break; + case NXT2004: + nxt200x_writebytes(state, 0x49, buf, 2); + nxt200x_writebytes(state, 0x4B, buf, 2); + break; + default: + return -EINVAL; + break; + } + + /* write agc control reg */ + buf[0] = 0x04; + nxt200x_writebytes(state, 0x41, buf, 1); + + nxt200x_microcontroller_start(state); + + if (state->demod_chip == NXT2004) { + nxt2004_microcontroller_init(state); + + /* ???? */ + buf[0] = 0xF0; + buf[1] = 0x00; + nxt200x_writebytes(state, 0x5C, buf, 2); + } + + /* adjacent channel detection should be done here, but I don't + have any stations with this need so I cannot test it */ + + return 0; +} + +static int nxt200x_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info) +{ + struct nxt200x_state *state = fe->demodulator_priv; + + switch (state->demod_chip) { + case NXT2002: + memcpy(fe_info, &nxt2002_info, sizeof (nxt2002_info)); + break; + case NXT2004: + memcpy(fe_info, &nxt2004_info, sizeof (nxt2004_info)); + break; + default: + break; + } + + return 0; +} + +static int nxt200x_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_DVBS; + + return 0; +} + static struct dvb_frontend_ops nxt200x_ops = { .info = { @@ -1235,6 +1538,10 @@ static struct dvb_frontend_ops nxt200x_o .read_signal_strength = nxt200x_read_signal_strength, .read_snr = nxt200x_read_snr, .read_ucblocks = nxt200x_read_ucblocks, + + .set_params = nxt200x_set_params, + .get_info = nxt200x_get_info, + .get_delsys = nxt200x_get_delsys, }; module_param(debug, int, 0644); @@ -1245,4 +1552,3 @@ MODULE_AUTHOR("Kirk Lapray, Michael Kruf MODULE_LICENSE("GPL"); EXPORT_SYMBOL(nxt200x_attach); - diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/nxt6000.c mp-bc1/linux/drivers/media/dvb/frontends/nxt6000.c --- v4l-dvb/linux/drivers/media/dvb/frontends/nxt6000.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/nxt6000.c 2006-07-17 23:44:47.000000000 +0400 @@ -81,7 +81,7 @@ static void nxt6000_reset(struct nxt6000 nxt6000_writereg(state, OFDM_COR_CTL, val | COREACT); } -static int nxt6000_set_bandwidth(struct nxt6000_state* state, fe_bandwidth_t bandwidth) +static int nxt6000_set_bandwidth_compat(struct nxt6000_state* state, fe_bandwidth_t bandwidth) { u16 nominal_rate; int result; @@ -110,7 +110,33 @@ static int nxt6000_set_bandwidth(struct return nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_2, (nominal_rate >> 8) & 0xFF); } -static int nxt6000_set_guard_interval(struct nxt6000_state* state, fe_guard_interval_t guard_interval) +static int nxt6000_set_bandwidth(struct nxt6000_state* state, + enum dvbfe_bandwidth bandwidth) +{ + u16 nominal_rate; + int result; + + switch (bandwidth) { + case DVBFE_BANDWIDTH_6_MHZ: + nominal_rate = 0x55B7; + break; + case DVBFE_BANDWIDTH_7_MHZ: + nominal_rate = 0x6400; + break; + case DVBFE_BANDWIDTH_8_MHZ: + nominal_rate = 0x7249; + break; + default: + return -EINVAL; + } + + if ((result = nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_1, nominal_rate & 0xFF)) < 0) + return result; + + return nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_2, (nominal_rate >> 8) & 0xFF); +} + +static int nxt6000_set_guard_interval_compat(struct nxt6000_state* state, fe_guard_interval_t guard_interval) { switch (guard_interval) { @@ -132,6 +158,23 @@ static int nxt6000_set_guard_interval(st } } +static int nxt6000_set_guard_interval(struct nxt6000_state* state, enum dvbfe_guard_interval guard_interval) +{ + switch (guard_interval) { + case DVBFE_GUARD_INTERVAL_1_32: + return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x00 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03)); + case DVBFE_GUARD_INTERVAL_1_16: + return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x01 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03)); + case DVBFE_GUARD_INTERVAL_AUTO: + case DVBFE_GUARD_INTERVAL_1_8: + return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x02 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03)); + case DVBFE_GUARD_INTERVAL_1_4: + return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x03 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03)); + default: + return -EINVAL; + } +} + static int nxt6000_set_inversion(struct nxt6000_state* state, fe_spectral_inversion_t inversion) { switch (inversion) { @@ -148,7 +191,7 @@ static int nxt6000_set_inversion(struct } } -static int nxt6000_set_transmission_mode(struct nxt6000_state* state, fe_transmit_mode_t transmission_mode) +static int nxt6000_set_transmission_mode_compat(struct nxt6000_state* state, fe_transmit_mode_t transmission_mode) { int result; @@ -173,6 +216,27 @@ static int nxt6000_set_transmission_mode } } +static int nxt6000_set_transmission_mode(struct nxt6000_state* state, enum dvbfe_transmission_mode transmission_mode) +{ + int result; + + switch (transmission_mode) { + case DVBFE_TRANSMISSION_MODE_2K: + if ((result = nxt6000_writereg(state, EN_DMD_RACQ, 0x00 | (nxt6000_readreg(state, EN_DMD_RACQ) & ~0x03))) < 0) + return result; + return nxt6000_writereg(state, OFDM_COR_MODEGUARD, (0x00 << 2) | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x04)); + case DVBFE_TRANSMISSION_MODE_8K: + case DVBFE_TRANSMISSION_MODE_AUTO: + if ((result = nxt6000_writereg(state, EN_DMD_RACQ, 0x02 | (nxt6000_readreg(state, EN_DMD_RACQ) & ~0x03))) < 0) + return result; + + return nxt6000_writereg(state, OFDM_COR_MODEGUARD, (0x01 << 2) | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x04)); + default: + return -EINVAL; + + } +} + static void nxt6000_setup(struct dvb_frontend* fe) { struct nxt6000_state* state = fe->demodulator_priv; @@ -462,16 +526,17 @@ static int nxt6000_set_frontend(struct d struct nxt6000_state* state = fe->demodulator_priv; int result; - if (fe->ops.tuner_ops.set_params) { - fe->ops.tuner_ops.set_params(fe, param); - 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, param); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); } - if ((result = nxt6000_set_bandwidth(state, param->u.ofdm.bandwidth)) < 0) + if ((result = nxt6000_set_bandwidth_compat(state, param->u.ofdm.bandwidth)) < 0) return result; - if ((result = nxt6000_set_guard_interval(state, param->u.ofdm.guard_interval)) < 0) + if ((result = nxt6000_set_guard_interval_compat(state, param->u.ofdm.guard_interval)) < 0) return result; - if ((result = nxt6000_set_transmission_mode(state, param->u.ofdm.transmission_mode)) < 0) + if ((result = nxt6000_set_transmission_mode_compat(state, param->u.ofdm.transmission_mode)) < 0) return result; if ((result = nxt6000_set_inversion(state, param->inversion)) < 0) return result; @@ -565,6 +630,62 @@ error: return NULL; } +static struct dvbfe_info dvbt_info = { + .name = "Nextwave NXT6000 DVB-T", + .delivery = DVBFE_DELSYS_DVBT, + .delsys = { + .dvbt.modulation = DVBFE_MOD_OFDM, + .dvbt.stream_priority = DVBFE_STREAM_PRIORITY_HP | + DVBFE_STREAM_PRIORITY_LP, + }, + + .frequency_min = 0, + .frequency_max = 863250000, + .frequency_step = 62500, + .symbol_rate_min = 0, + .symbol_rate_max = 9360000, + .symbol_rate_tolerance = 4000, +}; + +static int nxt6000_set_params(struct dvb_frontend* fe, + struct dvbfe_params *param) +{ + struct nxt6000_state* state = fe->demodulator_priv; + int result; + + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, param); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + } + + if ((result = nxt6000_set_bandwidth(state, param->delsys.dvbt.bandwidth)) < 0) + return result; + if ((result = nxt6000_set_guard_interval(state, param->delsys.dvbt.guard_interval)) < 0) + return result; + if ((result = nxt6000_set_transmission_mode(state, param->delsys.dvbt.transmission_mode)) < 0) + return result; + if ((result = nxt6000_set_inversion(state, param->inversion)) < 0) + return result; + + msleep(500); + return 0; +} + +static int nxt6000_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info) +{ + memcpy(fe_info, &dvbt_info, sizeof (dvbt_info)); + + return 0; +} + +static int nxt6000_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_DVBT; + + return 0; +} + static struct dvb_frontend_ops nxt6000_ops = { .info = { @@ -598,6 +719,10 @@ static struct dvb_frontend_ops nxt6000_o .read_ber = nxt6000_read_ber, .read_signal_strength = nxt6000_read_signal_strength, .read_snr = nxt6000_read_snr, + + .set_params = nxt6000_set_params, + .get_info = nxt6000_get_info, + .get_delsys = nxt6000_get_delsys, }; module_param(debug, int, 0644); diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/or51132.c mp-bc1/linux/drivers/media/dvb/frontends/or51132.c --- v4l-dvb/linux/drivers/media/dvb/frontends/or51132.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/or51132.c 2006-07-17 23:44:57.000000000 +0400 @@ -382,9 +382,81 @@ static int or51132_set_parameters(struct or51132_setmode(fe); } + if (fe->ops.tuner_ops.set_params_compat) { + fe->ops.tuner_ops.set_params_compat(fe, param); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + } + + /* Set to current mode */ + or51132_setmode(fe); + + /* Update current frequency */ + state->current_frequency = param->frequency; + return 0; +} + +static int or51132_set_params(struct dvb_frontend* fe, + struct dvbfe_params *param) +{ + int ret; + struct or51132_state* state = fe->demodulator_priv; + const struct firmware *fw; + const char *fwname; + int clock_mode; + + /* Upload new firmware only if we need a different one */ + if (modulation_fw_class(state->current_modulation) != + modulation_fw_class(param->delsys.atsc.modulation)) { + switch(modulation_fw_class(param->delsys.atsc.modulation)) { + case DVBFE_MOD_VSB8: + dprintk("set_parameters VSB MODE\n"); + fwname = OR51132_VSB_FIRMWARE; + + /* Set non-punctured clock for VSB */ + clock_mode = 0; + break; + case DVBFE_MOD_QAM64: + case DVBFE_MOD_QAM256: + dprintk("set_parameters QAM MODE\n"); + fwname = OR51132_QAM_FIRMWARE; + + /* Set punctured clock for QAM */ + clock_mode = 1; + break; + default: + printk("or51132: Modulation type(%d) UNSUPPORTED\n", + param->delsys.atsc.modulation); + return -1; + } + printk("or51132: Waiting for firmware upload(%s)...\n", + fwname); + ret = request_firmware(&fw, fwname, &state->i2c->dev); + if (ret) { + printk(KERN_WARNING "or51132: No firmware up" + "loaded(timeout or file not found?)\n"); + return ret; + } + ret = or51132_load_firmware(fe, fw); + release_firmware(fw); + if (ret) { + printk(KERN_WARNING "or51132: Writing firmware to " + "device failed!\n"); + return ret; + } + printk("or51132: Firmware upload complete.\n"); + state->config->set_ts_params(fe, clock_mode); + } + /* Change only if we are actually changing the modulation */ + if (state->current_modulation != param->delsys.atsc.modulation) { + state->current_modulation = param->delsys.atsc.modulation; + or51132_setmode(fe); + } + if (fe->ops.tuner_ops.set_params) { fe->ops.tuner_ops.set_params(fe, param); - if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); } /* Set to current mode */ @@ -433,6 +505,50 @@ static int or51132_get_parameters(struct return 0; } +static int or51132_get_params(struct dvb_frontend* fe, + struct dvbfe_params *param) +{ + struct or51132_state* state = fe->demodulator_priv; + u8 buf[2]; + + /* Receiver Status */ + buf[0]=0x04; + buf[1]=0x00; + msleep(30); /* 30ms */ + if (i2c_writebytes(state,state->config->demod_address,buf,2)) { + printk(KERN_WARNING "or51132: get_parameters write error\n"); + return -EREMOTEIO; + } + msleep(30); /* 30ms */ + if (i2c_readbytes(state,state->config->demod_address,buf,2)) { + printk(KERN_WARNING "or51132: get_parameters read error\n"); + return -EREMOTEIO; + } + switch(buf[0]) { + case 0x06: + param->delsys.atsc.modulation = DVBFE_MOD_VSB8; + break; + case 0x43: + param->delsys.atsc.modulation = DVBFE_MOD_QAM64; + break; + case 0x45: + param->delsys.atsc.modulation = DVBFE_MOD_QAM256; + break; + default: + printk(KERN_WARNING "or51132: unknown status 0x%02x\n", + buf[0]); + return -EREMOTEIO; + } + + /* FIXME: Read frequency from frontend, take AFC into account */ + param->frequency = state->current_frequency; + + /* FIXME: How to read inversion setting? Receiver 6 register? */ + param->inversion = INVERSION_AUTO; + + return 0; +} + static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status) { struct or51132_state* state = fe->demodulator_priv; @@ -630,6 +746,33 @@ error: return NULL; } +static struct dvbfe_info atsc_info = { + .name = "Oren OR51132 ATSC", + .delivery = DVBFE_DELSYS_ATSC, + .delsys = { + .atsc.modulation = DVBFE_MOD_VSB8 |DVBFE_MOD_QAM64 | + DVBFE_MOD_QAM256 + }, + + .frequency_min = 44000000, + .frequency_max = 958000000, + .frequency_step = 166666, +}; + +static int or51132_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info) +{ + memcpy(fe_info, &atsc_info, sizeof (atsc_info)); + + return 0; +} + +static int or51132_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_ATSC; + + return 0; +} + static struct dvb_frontend_ops or51132_ops = { .info = { @@ -658,6 +801,11 @@ static struct dvb_frontend_ops or51132_o .read_signal_strength = or51132_read_signal_strength, .read_snr = or51132_read_snr, .read_ucblocks = or51132_read_ucblocks, + + .set_params = or51132_set_params, + .get_params = or51132_get_params, + .get_info = or51132_get_info, + .get_delsys = or51132_get_delsys, }; module_param(debug, int, 0644); diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/or51211.c mp-bc1/linux/drivers/media/dvb/frontends/or51211.c --- v4l-dvb/linux/drivers/media/dvb/frontends/or51211.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/or51211.c 2006-07-17 23:45:05.000000000 +0400 @@ -263,6 +263,52 @@ static int or51211_set_parameters(struct return 0; } +static int or51211_set_params(struct dvb_frontend* fe, + struct dvbfe_params *param) +{ + struct or51211_state* state = fe->demodulator_priv; + u32 freq = 0; + u16 tunerfreq = 0; + u8 buf[4]; + + /* Change only if we are actually changing the channel */ + if (state->current_frequency != param->frequency) { + freq = 44000 + (param->frequency/1000); + tunerfreq = freq * 16/1000; + + dprintk("set_parameters frequency = %d (tunerfreq = %d)\n", + param->frequency,tunerfreq); + + buf[0] = (tunerfreq >> 8) & 0x7F; + buf[1] = (tunerfreq & 0xFF); + buf[2] = 0x8E; + + if (param->frequency < 157250000) { + buf[3] = 0xA0; + dprintk("set_parameters VHF low range\n"); + } else if (param->frequency < 454000000) { + buf[3] = 0x90; + dprintk("set_parameters VHF high range\n"); + } else { + buf[3] = 0x30; + dprintk("set_parameters UHF range\n"); + } + dprintk("set_parameters tuner bytes: 0x%02x 0x%02x " + "0x%02x 0x%02x\n",buf[0],buf[1],buf[2],buf[3]); + + if (i2c_writebytes(state,0xC2>>1,buf,4)) + printk(KERN_WARNING "or51211:set_parameters error " + "writing to tuner\n"); + + /* Set to ATSC mode */ + or51211_setmode(fe,0); + + /* Update current frequency */ + state->current_frequency = param->frequency; + } + return 0; +} + static int or51211_read_status(struct dvb_frontend* fe, fe_status_t* status) { struct or51211_state* state = fe->demodulator_priv; @@ -597,6 +643,32 @@ error: return NULL; } +static struct dvbfe_info atsc_info = { + .name = "Oren OR51211 ATSC", + .delivery = DVBFE_DELSYS_ATSC, + .delsys = { + .atsc.modulation = DVBFE_MOD_VSB8 + }, + + .frequency_min = 44000000, + .frequency_max = 958000000, + .frequency_step = 166666, +}; + +static int or51211_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info) +{ + memcpy(fe_info, &atsc_info, sizeof (atsc_info)); + + return 0; +} + +static int or51211_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_ATSC; + + return 0; +} + static struct dvb_frontend_ops or51211_ops = { .info = { @@ -623,6 +695,10 @@ static struct dvb_frontend_ops or51211_o .read_signal_strength = or51211_read_signal_strength, .read_snr = or51211_read_snr, .read_ucblocks = or51211_read_ucblocks, + + .set_params = or51211_set_params, + .get_info = or51211_get_info, + .get_delsys = or51211_get_delsys, }; module_param(debug, int, 0644); @@ -633,4 +709,3 @@ MODULE_AUTHOR("Kirk Lapray"); MODULE_LICENSE("GPL"); EXPORT_SYMBOL(or51211_attach); - diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/s5h1420.c mp-bc1/linux/drivers/media/dvb/frontends/s5h1420.c --- v4l-dvb/linux/drivers/media/dvb/frontends/s5h1420.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/s5h1420.c 2006-07-17 23:45:23.000000000 +0400 @@ -419,8 +419,8 @@ static void s5h1420_reset(struct s5h1420 udelay(10); } -static void s5h1420_setsymbolrate(struct s5h1420_state* state, - struct dvb_frontend_parameters *p) +static void s5h1420_setsymbolrate_compat(struct s5h1420_state* state, + struct dvb_frontend_parameters *p) { u64 val; @@ -437,6 +437,24 @@ static void s5h1420_setsymbolrate(struct s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) | 0x80); } +static void s5h1420_setsymbolrate(struct s5h1420_state* state, + struct dvbfe_params *p) +{ + u64 val; + + val = ((u64) p->delsys.dvbs.symbol_rate / 1000ULL) * (1ULL<<24); + if (p->delsys.dvbs.symbol_rate <= 21000000) { + val *= 2; + } + do_div(val, (state->fclk / 1000)); + + s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) & 0x7f); + s5h1420_writereg(state, 0x11, val >> 16); + s5h1420_writereg(state, 0x12, val >> 8); + s5h1420_writereg(state, 0x13, val & 0xff); + s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) | 0x80); +} + static u32 s5h1420_getsymbolrate(struct s5h1420_state* state) { u64 val = 0; @@ -492,8 +510,8 @@ static int s5h1420_getfreqoffset(struct return val; } -static void s5h1420_setfec_inversion(struct s5h1420_state* state, - struct dvb_frontend_parameters *p) +static void s5h1420_setfec_inversion_compat(struct s5h1420_state* state, + struct dvb_frontend_parameters *p) { u8 inversion = 0; @@ -544,7 +562,61 @@ static void s5h1420_setfec_inversion(str } } -static fe_code_rate_t s5h1420_getfec(struct s5h1420_state* state) +static void s5h1420_setfec_inversion(struct s5h1420_state* state, + struct dvbfe_params *p) +{ + u8 inversion = 0; + + if (p->inversion == INVERSION_OFF) { + inversion = state->config->invert ? 0x08 : 0; + } else if (p->inversion == INVERSION_ON) { + inversion = state->config->invert ? 0 : 0x08; + } + + if ((p->delsys.dvbs.fec == DVBFE_FEC_AUTO) || + (p->inversion == INVERSION_AUTO)) { + + s5h1420_writereg(state, 0x30, 0x3f); + s5h1420_writereg(state, 0x31, 0x00 | inversion); + } else { + switch (p->delsys.dvbs.fec) { + case DVBFE_FEC_1_2: + s5h1420_writereg(state, 0x30, 0x01); + s5h1420_writereg(state, 0x31, 0x10 | inversion); + break; + + case DVBFE_FEC_2_3: + s5h1420_writereg(state, 0x30, 0x02); + s5h1420_writereg(state, 0x31, 0x11 | inversion); + break; + + case DVBFE_FEC_3_4: + s5h1420_writereg(state, 0x30, 0x04); + s5h1420_writereg(state, 0x31, 0x12 | inversion); + break; + + case DVBFE_FEC_5_6: + s5h1420_writereg(state, 0x30, 0x08); + s5h1420_writereg(state, 0x31, 0x13 | inversion); + break; + + case DVBFE_FEC_6_7: + s5h1420_writereg(state, 0x30, 0x10); + s5h1420_writereg(state, 0x31, 0x14 | inversion); + break; + + case DVBFE_FEC_7_8: + s5h1420_writereg(state, 0x30, 0x20); + s5h1420_writereg(state, 0x31, 0x15 | inversion); + break; + + default: + return; + } + } +} + +static fe_code_rate_t s5h1420_getfec_compat(struct s5h1420_state* state) { switch(s5h1420_readreg(state, 0x32) & 0x07) { case 0: @@ -569,6 +641,31 @@ static fe_code_rate_t s5h1420_getfec(str return FEC_NONE; } +static fe_code_rate_t s5h1420_getfec(struct s5h1420_state* state) +{ + switch(s5h1420_readreg(state, 0x32) & 0x07) { + case 0: + return DVBFE_FEC_1_2; + + case 1: + return DVBFE_FEC_2_3; + + case 2: + return DVBFE_FEC_3_4; + + case 3: + return DVBFE_FEC_5_6; + + case 4: + return DVBFE_FEC_6_7; + + case 5: + return DVBFE_FEC_7_8; + } + + return DVBFE_FEC_NONE; +} + static fe_spectral_inversion_t s5h1420_getinversion(struct s5h1420_state* state) { if (s5h1420_readreg(state, 0x32) & 0x08) @@ -594,9 +691,10 @@ static int s5h1420_set_frontend(struct d (state->fec_inner == p->u.qpsk.fec_inner) && (state->symbol_rate == p->u.qpsk.symbol_rate)) { - 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); } if (fe->ops.tuner_ops.get_frequency) { u32 tmp; @@ -651,9 +749,104 @@ static int s5h1420_set_frontend(struct d s5h1420_writereg(state, 0x05, s5h1420_readreg(state, 0x05) | 1); /* set tuner PLL */ + 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); + s5h1420_setfreqoffset(state, 0); + } + + /* set the reset of the parameters */ + s5h1420_setsymbolrate_compat(state, p); + s5h1420_setfec_inversion_compat(state, p); + + state->fec_inner = p->u.qpsk.fec_inner; + state->symbol_rate = p->u.qpsk.symbol_rate; + state->postlocked = 0; + state->tunedfreq = p->frequency; + return 0; +} + +static int s5h1420_set_params(struct dvb_frontend* fe, + struct dvbfe_params *p) +{ + struct s5h1420_state* state = fe->demodulator_priv; + int frequency_delta; + struct dvb_frontend_tune_settings fesettings; + + /* check if we should do a fast-tune */ +// memcpy(&fesettings.parameters, p, sizeof(struct dvb_frontend_parameters)); + memcpy(&fesettings.fe_params, p, sizeof(struct dvb_frontend_parameters)); + s5h1420_get_tune_settings(fe, &fesettings); + frequency_delta = p->frequency - state->tunedfreq; + if ((frequency_delta > -fesettings.max_drift) && + (frequency_delta < fesettings.max_drift) && + (frequency_delta != 0) && + (state->fec_inner == p->delsys.dvbs.fec) && + (state->symbol_rate == p->delsys.dvbs.symbol_rate)) { + + 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.get_frequency) { + u32 tmp; + fe->ops.tuner_ops.get_frequency(fe, &tmp); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + s5h1420_setfreqoffset(state, p->frequency - tmp); + } else { + s5h1420_setfreqoffset(state, 0); + } + return 0; + } + + /* first of all, software reset */ + s5h1420_reset(state); + + /* set s5h1420 fclk PLL according to desired symbol rate */ + if (p->delsys.dvbs.symbol_rate > 28000000) { + state->fclk = 88000000; + s5h1420_writereg(state, 0x03, 0x50); + s5h1420_writereg(state, 0x04, 0x40); + s5h1420_writereg(state, 0x05, 0xae); + } else if (p->delsys.dvbs.symbol_rate > 21000000) { + state->fclk = 59000000; + s5h1420_writereg(state, 0x03, 0x33); + s5h1420_writereg(state, 0x04, 0x40); + s5h1420_writereg(state, 0x05, 0xae); + } else { + state->fclk = 88000000; + s5h1420_writereg(state, 0x03, 0x50); + s5h1420_writereg(state, 0x04, 0x40); + s5h1420_writereg(state, 0x05, 0xac); + } + + /* set misc registers */ + s5h1420_writereg(state, 0x02, 0x00); + s5h1420_writereg(state, 0x06, 0x00); + s5h1420_writereg(state, 0x07, 0xb0); + s5h1420_writereg(state, 0x0a, 0xe7); + s5h1420_writereg(state, 0x0b, 0x78); + s5h1420_writereg(state, 0x0c, 0x48); + s5h1420_writereg(state, 0x0d, 0x6b); + s5h1420_writereg(state, 0x2e, 0x8e); + s5h1420_writereg(state, 0x35, 0x33); + s5h1420_writereg(state, 0x38, 0x01); + s5h1420_writereg(state, 0x39, 0x7d); + s5h1420_writereg(state, 0x3a, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32)); + s5h1420_writereg(state, 0x3c, 0x00); + s5h1420_writereg(state, 0x45, 0x61); + s5h1420_writereg(state, 0x46, 0x1d); + + /* start QPSK */ + s5h1420_writereg(state, 0x05, s5h1420_readreg(state, 0x05) | 1); + + /* set tuner PLL */ 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.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); s5h1420_setfreqoffset(state, 0); } @@ -661,8 +854,8 @@ static int s5h1420_set_frontend(struct d s5h1420_setsymbolrate(state, p); s5h1420_setfec_inversion(state, p); - state->fec_inner = p->u.qpsk.fec_inner; - state->symbol_rate = p->u.qpsk.symbol_rate; + state->fec_inner = p->delsys.dvbs.fec; + state->symbol_rate = p->delsys.dvbs.symbol_rate; state->postlocked = 0; state->tunedfreq = p->frequency; return 0; @@ -676,7 +869,20 @@ static int s5h1420_get_frontend(struct d p->frequency = state->tunedfreq + s5h1420_getfreqoffset(state); p->inversion = s5h1420_getinversion(state); p->u.qpsk.symbol_rate = s5h1420_getsymbolrate(state); - p->u.qpsk.fec_inner = s5h1420_getfec(state); + p->u.qpsk.fec_inner = s5h1420_getfec_compat(state); + + return 0; +} + +static int s5h1420_get_params(struct dvb_frontend* fe, + struct dvbfe_params *p) +{ + struct s5h1420_state* state = fe->demodulator_priv; + + p->frequency = state->tunedfreq + s5h1420_getfreqoffset(state); + p->inversion = s5h1420_getinversion(state); + p->delsys.dvbs.symbol_rate = s5h1420_getsymbolrate(state); + p->delsys.dvbs.fec = s5h1420_getfec(state); return 0; } @@ -684,32 +890,59 @@ static int s5h1420_get_frontend(struct d static int s5h1420_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings) { - if (fesettings->parameters.u.qpsk.symbol_rate > 20000000) { - fesettings->min_delay_ms = 50; - fesettings->step_size = 2000; - fesettings->max_drift = 8000; - } else if (fesettings->parameters.u.qpsk.symbol_rate > 12000000) { - fesettings->min_delay_ms = 100; - fesettings->step_size = 1500; - fesettings->max_drift = 9000; - } else if (fesettings->parameters.u.qpsk.symbol_rate > 8000000) { - fesettings->min_delay_ms = 100; - fesettings->step_size = 1000; - fesettings->max_drift = 8000; - } else if (fesettings->parameters.u.qpsk.symbol_rate > 4000000) { - fesettings->min_delay_ms = 100; - fesettings->step_size = 500; - fesettings->max_drift = 7000; - } else if (fesettings->parameters.u.qpsk.symbol_rate > 2000000) { - fesettings->min_delay_ms = 200; - fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000); - fesettings->max_drift = 14 * fesettings->step_size; + if (fe->legacy) { + if (fesettings->parameters.u.qpsk.symbol_rate > 20000000) { + fesettings->min_delay_ms = 50; + fesettings->step_size = 2000; + fesettings->max_drift = 8000; + } else if (fesettings->parameters.u.qpsk.symbol_rate > 12000000) { + fesettings->min_delay_ms = 100; + fesettings->step_size = 1500; + fesettings->max_drift = 9000; + } else if (fesettings->parameters.u.qpsk.symbol_rate > 8000000) { + fesettings->min_delay_ms = 100; + fesettings->step_size = 1000; + fesettings->max_drift = 8000; + } else if (fesettings->parameters.u.qpsk.symbol_rate > 4000000) { + fesettings->min_delay_ms = 100; + fesettings->step_size = 500; + fesettings->max_drift = 7000; + } else if (fesettings->parameters.u.qpsk.symbol_rate > 2000000) { + fesettings->min_delay_ms = 200; + fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000); + fesettings->max_drift = 14 * fesettings->step_size; + } else { + fesettings->min_delay_ms = 200; + fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000); + fesettings->max_drift = 18 * fesettings->step_size; + } } else { - fesettings->min_delay_ms = 200; - fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000); - fesettings->max_drift = 18 * fesettings->step_size; + if (fesettings->fe_params.delsys.dvbs.symbol_rate > 20000000) { + fesettings->min_delay_ms = 50; + fesettings->step_size = 2000; + fesettings->max_drift = 8000; + } else if (fesettings->fe_params.delsys.dvbs.symbol_rate > 12000000) { + fesettings->min_delay_ms = 100; + fesettings->step_size = 1500; + fesettings->max_drift = 9000; + } else if (fesettings->fe_params.delsys.dvbs.symbol_rate > 8000000) { + fesettings->min_delay_ms = 100; + fesettings->step_size = 1000; + fesettings->max_drift = 8000; + } else if (fesettings->fe_params.delsys.dvbs.symbol_rate > 4000000) { + fesettings->min_delay_ms = 100; + fesettings->step_size = 500; + fesettings->max_drift = 7000; + } else if (fesettings->fe_params.delsys.dvbs.symbol_rate > 2000000) { + fesettings->min_delay_ms = 200; + fesettings->step_size = (fesettings->fe_params.delsys.dvbs.symbol_rate / 8000); + fesettings->max_drift = 14 * fesettings->step_size; + } else { + fesettings->min_delay_ms = 200; + fesettings->step_size = (fesettings->fe_params.delsys.dvbs.symbol_rate / 8000); + fesettings->max_drift = 18 * fesettings->step_size; + } } - return 0; } @@ -786,6 +1019,38 @@ error: return NULL; } +static struct dvbfe_info dvbs_info = { + .name = "Samsung S5H1420 DVB-S", + .delivery = DVBFE_DELSYS_DVBS, + .delsys = { + .dvbs.modulation = DVBFE_DELSYS_DVBS, + .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 = 125, + .frequency_tolerance = 29500, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, +}; + +static int s5h1420_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info) +{ + memcpy(fe_info, &dvbs_info, sizeof (dvbs_info)); + + return 0; +} + +static int s5h1420_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_DVBS; + + return 0; +} + static struct dvb_frontend_ops s5h1420_ops = { .info = { @@ -824,6 +1089,11 @@ static struct dvb_frontend_ops s5h1420_o .diseqc_send_burst = s5h1420_send_burst, .set_tone = s5h1420_set_tone, .set_voltage = s5h1420_set_voltage, + + .set_params = s5h1420_set_params, + .get_params = s5h1420_get_params, + .get_info = s5h1420_get_info, + .get_delsys = s5h1420_get_delsys, }; module_param(debug, int, 0644); diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/sp8870.c mp-bc1/linux/drivers/media/dvb/frontends/sp8870.c --- v4l-dvb/linux/drivers/media/dvb/frontends/sp8870.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/sp8870.c 2006-07-17 23:45:30.000000000 +0400 @@ -169,7 +169,7 @@ static int sp8870_read_data_valid_signal return (sp8870_readreg(state, 0x0D02) > 0); } -static int configure_reg0xc05 (struct dvb_frontend_parameters *p, u16 *reg0xc05) +static int configure_reg0xc05_compat(struct dvb_frontend_parameters *p, u16 *reg0xc05) { int known_parameters = 1; @@ -240,6 +240,83 @@ static int configure_reg0xc05 (struct dv return 0; } +static int configure_reg0xc05(struct dvbfe_params *p, u16 *reg0xc05) +{ + int known_parameters = 1; + + *reg0xc05 = 0x000; + + switch (p->delsys.dvbt.constellation) { + case DVBFE_MOD_QPSK: + break; + case DVBFE_MOD_QAM16: + *reg0xc05 |= (1 << 10); + break; + case DVBFE_MOD_QAM64: + *reg0xc05 |= (2 << 10); + break; + case DVBFE_MOD_QAMAUTO: + known_parameters = 0; + break; + default: + return -EINVAL; + }; + + switch (p->delsys.dvbt.hierarchy) { + case DVBFE_HIERARCHY_OFF: + break; + case DVBFE_HIERARCHY_ON: + switch (p->delsys.dvbt.alpha) { + case DVBFE_ALPHA_1: + *reg0xc05 |= (1 << 7); + break; + case DVBFE_ALPHA_2: + *reg0xc05 |= (2 << 7); + break; + case DVBFE_ALPHA_4: + *reg0xc05 |= (3 << 7); + break; + default: + return -EINVAL; + } + break; + case HIERARCHY_AUTO: + known_parameters = 0; + break; + default: + return -EINVAL; + }; + + switch (p->delsys.dvbt.code_rate_HP) { + case DVBFE_FEC_1_2: + break; + case DVBFE_FEC_2_3: + *reg0xc05 |= (1 << 3); + break; + case DVBFE_FEC_3_4: + *reg0xc05 |= (2 << 3); + break; + case DVBFE_FEC_5_6: + *reg0xc05 |= (3 << 3); + break; + case DVBFE_FEC_7_8: + *reg0xc05 |= (4 << 3); + break; + case DVBFE_FEC_AUTO: + known_parameters = 0; + break; + default: + return -EINVAL; + }; + + if (known_parameters) + *reg0xc05 |= (2 << 1); /* use specified parameters */ + else + *reg0xc05 |= (1 << 1); /* enable autoprobing */ + + return 0; +} + static int sp8870_wake_up(struct sp8870_state* state) { // enable TS output and interface pins @@ -253,16 +330,17 @@ static int sp8870_set_frontend_parameter int err; u16 reg0xc05; - if ((err = configure_reg0xc05(p, ®0xc05))) + if ((err = configure_reg0xc05_compat(p, ®0xc05))) return err; // system controller stop sp8870_microcontroller_stop(state); // set tuner parameters - 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); } // sample rate correction bit [23..17] @@ -579,6 +657,92 @@ error: return NULL; } +static struct dvbfe_info dvbt_info = { + .name = "Spase SP8870 DVB-T", + .delivery = DVBFE_DELSYS_DVBT, + .delsys = { + .dvbt.modulation = DVBFE_MOD_OFDM, + .dvbt.stream_priority = DVBFE_STREAM_PRIORITY_HP | + DVBFE_STREAM_PRIORITY_LP, + }, + + .frequency_min = 470000000, + .frequency_max = 860000000, + .frequency_step = 166666, +}; + +static int sp8870_set_params(struct dvb_frontend* fe, + struct dvbfe_params *p) +{ + struct sp8870_state* state = fe->demodulator_priv; + int err; + u16 reg0xc05; + + if ((err = configure_reg0xc05(p, ®0xc05))) + return err; + + // system controller stop + sp8870_microcontroller_stop(state); + + // set tuner parameters + 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); + } + + // sample rate correction bit [23..17] + sp8870_writereg(state, 0x0319, 0x000A); + + // sample rate correction bit [16..0] + sp8870_writereg(state, 0x031A, 0x0AAB); + + // integer carrier offset + sp8870_writereg(state, 0x0309, 0x0400); + + // fractional carrier offset + sp8870_writereg(state, 0x030A, 0x0000); + + // filter for 6/7/8 Mhz channel + if (p->delsys.dvbt.bandwidth == DVBFE_BANDWIDTH_6_MHZ) + sp8870_writereg(state, 0x0311, 0x0002); + else if (p->delsys.dvbt.bandwidth == DVBFE_BANDWIDTH_7_MHZ) + sp8870_writereg(state, 0x0311, 0x0001); + else + sp8870_writereg(state, 0x0311, 0x0000); + + // scan order: 2k first = 0x0000, 8k first = 0x0001 + if (p->delsys.dvbt.transmission_mode == DVBFE_TRANSMISSION_MODE_2K) + sp8870_writereg(state, 0x0338, 0x0000); + else + sp8870_writereg(state, 0x0338, 0x0001); + + sp8870_writereg(state, 0xc05, reg0xc05); + + // read status reg in order to clear pending irqs + sp8870_readreg(state, 0x200); + + // system controller start + sp8870_microcontroller_start(state); + + return 0; +} + + +static int sp8870_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info) +{ + memcpy(fe_info, &dvbt_info, sizeof (dvbt_info)); + + return 0; +} + +static int sp8870_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_DVBT; + + return 0; +} + static struct dvb_frontend_ops sp8870_ops = { .info = { @@ -608,6 +772,10 @@ static struct dvb_frontend_ops sp8870_op .read_ber = sp8870_read_ber, .read_signal_strength = sp8870_read_signal_strength, .read_ucblocks = sp8870_read_uncorrected_blocks, + + .set_params = sp8870_set_params, + .get_info = sp8870_get_info, + .get_delsys = sp8870_get_delsys, }; module_param(debug, int, 0644); diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/sp887x.c mp-bc1/linux/drivers/media/dvb/frontends/sp887x.c --- v4l-dvb/linux/drivers/media/dvb/frontends/sp887x.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/sp887x.c 2006-07-17 23:45:35.000000000 +0400 @@ -210,7 +210,7 @@ static int sp887x_initial_setup (struct return 0; }; -static int configure_reg0xc05 (struct dvb_frontend_parameters *p, u16 *reg0xc05) +static int configure_reg0xc05_compat(struct dvb_frontend_parameters *p, u16 *reg0xc05) { int known_parameters = 1; @@ -281,6 +281,82 @@ static int configure_reg0xc05 (struct dv return 0; } +static int configure_reg0xc05(struct dvbfe_params *p, u16 *reg0xc05) +{ + int known_parameters = 1; + + *reg0xc05 = 0x000; + + switch (p->delsys.dvbt.constellation) { + case DVBFE_MOD_QPSK: + break; + case DVBFE_MOD_QAM16: + *reg0xc05 |= (1 << 10); + break; + case DVBFE_MOD_QAM64: + *reg0xc05 |= (2 << 10); + break; + case DVBFE_MOD_QAMAUTO: + known_parameters = 0; + break; + default: + return -EINVAL; + }; + + switch (p->delsys.dvbt.hierarchy) { + case DVBFE_HIERARCHY_OFF: + break; + case DVBFE_HIERARCHY_ON: + break; + switch (p->delsys.dvbt.alpha) { + case DVBFE_ALPHA_1: + *reg0xc05 |= (1 << 7); + break; + case DVBFE_ALPHA_2: + *reg0xc05 |= (2 << 7); + break; + case DVBFE_ALPHA_4: + *reg0xc05 |= (3 << 7); + break; + } + break; + case DVBFE_HIERARCHY_AUTO: + known_parameters = 0; + break; + default: + return -EINVAL; + }; + + switch (p->delsys.dvbt.code_rate_HP) { + case DVBFE_FEC_1_2: + break; + case DVBFE_FEC_2_3: + *reg0xc05 |= (1 << 3); + break; + case DVBFE_FEC_3_4: + *reg0xc05 |= (2 << 3); + break; + case DVBFE_FEC_5_6: + *reg0xc05 |= (3 << 3); + break; + case DVBFE_FEC_7_8: + *reg0xc05 |= (4 << 3); + break; + case DVBFE_FEC_AUTO: + known_parameters = 0; + break; + default: + return -EINVAL; + }; + + if (known_parameters) + *reg0xc05 |= (2 << 1); /* use specified parameters */ + else + *reg0xc05 |= (1 << 1); /* enable autoprobing */ + + return 0; +} + /** * estimates division of two 24bit numbers, * derived from the ves1820/stv0299 driver code @@ -303,9 +379,9 @@ static void divide (int n, int d, int *q } } -static void sp887x_correct_offsets (struct sp887x_state* state, - struct dvb_frontend_parameters *p, - int actual_freq) +static void sp887x_correct_offsets_compat(struct sp887x_state* state, + struct dvb_frontend_parameters *p, + int actual_freq) { static const u32 srate_correction [] = { 1879617, 4544878, 8098561 }; int bw_index = p->u.ofdm.bandwidth - BANDWIDTH_8_MHZ; @@ -334,6 +410,38 @@ static void sp887x_correct_offsets (stru sp887x_writereg(state, 0x30a, frequency_shift & 0xfff); } +static void sp887x_correct_offsets(struct sp887x_state* state, + struct dvbfe_params *p, + int actual_freq) +{ + static const u32 srate_correction [] = { 1879617, 0, 4544878, 8098561, 0 }; + + int bw_index = p->delsys.dvbt.bandwidth - DVBFE_BANDWIDTH_8_MHZ; + int freq_offset = actual_freq - p->frequency; + int sysclock = 61003; //[kHz] + int ifreq = 36000000; + int freq; + int frequency_shift; + + if (p->inversion == INVERSION_ON) + freq = ifreq - freq_offset; + else + freq = ifreq + freq_offset; + + divide(freq / 333, sysclock, NULL, &frequency_shift); + + if (p->inversion == INVERSION_ON) + frequency_shift = -frequency_shift; + + /* sample rate correction */ + sp887x_writereg(state, 0x319, srate_correction[fls(bw_index)] >> 12); + sp887x_writereg(state, 0x31a, srate_correction[fls(bw_index)] & 0xfff); + + /* carrier offset correction */ + sp887x_writereg(state, 0x309, frequency_shift >> 12); + sp887x_writereg(state, 0x30a, frequency_shift & 0xfff); +} + static int sp887x_setup_frontend_parameters (struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { @@ -346,15 +454,16 @@ static int sp887x_setup_frontend_paramet p->u.ofdm.bandwidth != BANDWIDTH_6_MHZ) return -EINVAL; - if ((err = configure_reg0xc05(p, ®0xc05))) + if ((err = configure_reg0xc05_compat(p, ®0xc05))) return err; sp887x_microcontroller_stop(state); /* setup the PLL */ - 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); } if (fe->ops.tuner_ops.get_frequency) { fe->ops.tuner_ops.get_frequency(fe, &actual_freq); @@ -366,7 +475,7 @@ static int sp887x_setup_frontend_paramet /* read status reg in order to clear u.ofdm.bandwidth == BANDWIDTH_6_MHZ) @@ -578,6 +687,105 @@ error: return NULL; } +static struct dvbfe_info dvbt_info = { + .name = "Spase SP887x DVB-T", + .delivery = DVBFE_DELSYS_DVBT, + .delsys = { + .dvbt.modulation = DVBFE_MOD_OFDM, + .dvbt.stream_priority = DVBFE_STREAM_PRIORITY_HP | + DVBFE_STREAM_PRIORITY_LP, + }, + + .frequency_min = 50500000, + .frequency_max = 858000000, + .frequency_step = 166666, +}; + +static int sp887x_set_params(struct dvb_frontend* fe, + struct dvbfe_params *p) +{ + struct sp887x_state* state = fe->demodulator_priv; + int actual_freq, err; + u16 val, reg0xc05; + + if (p->delsys.dvbt.bandwidth != DVBFE_BANDWIDTH_8_MHZ && + p->delsys.dvbt.bandwidth != DVBFE_BANDWIDTH_7_MHZ && + p->delsys.dvbt.bandwidth != DVBFE_BANDWIDTH_6_MHZ) + return -EINVAL; + + if ((err = configure_reg0xc05(p, ®0xc05))) + return err; + + sp887x_microcontroller_stop(state); + + /* setup the PLL */ + 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.get_frequency) { + fe->ops.tuner_ops.get_frequency(fe, &actual_freq); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + } else { + actual_freq = p->frequency; + } + + /* read status reg in order to clear delsys.dvbt.bandwidth == DVBFE_BANDWIDTH_6_MHZ) + val = 2; + else if (p->delsys.dvbt.bandwidth == DVBFE_BANDWIDTH_7_MHZ) + val = 1; + else + val = 0; + + sp887x_writereg(state, 0x311, val); + + /* scan order: 2k first = 0, 8k first = 1 */ + if (p->delsys.dvbt.transmission_mode == DVBFE_TRANSMISSION_MODE_2K) + sp887x_writereg(state, 0x338, 0x000); + else + sp887x_writereg(state, 0x338, 0x001); + + sp887x_writereg(state, 0xc05, reg0xc05); + + if (p->delsys.dvbt.bandwidth == DVBFE_BANDWIDTH_6_MHZ) + val = 2 << 3; + else if (p->delsys.dvbt.bandwidth == DVBFE_BANDWIDTH_7_MHZ) + val = 3 << 3; + else + val = 0 << 3; + + /* enable OFDM and SAW bits as lock indicators in sync register 0xf17, + * optimize algorithm for given bandwidth... + */ + sp887x_writereg(state, 0xf14, 0x160 | val); + sp887x_writereg(state, 0xf15, 0x000); + + sp887x_microcontroller_start(state); + return 0; +} + +static int sp887x_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info) +{ + memcpy(fe_info, &dvbt_info, sizeof (dvbt_info)); + + return 0; +} + +static int sp887x_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_DVBT; + + return 0; +} + static struct dvb_frontend_ops sp887x_ops = { .info = { @@ -606,6 +814,10 @@ static struct dvb_frontend_ops sp887x_op .read_signal_strength = sp887x_read_signal_strength, .read_snr = sp887x_read_snr, .read_ucblocks = sp887x_read_ucblocks, + + .set_params = sp887x_set_params, + .get_info = sp887x_get_info, + .get_delsys = sp887x_get_delsys, }; module_param(debug, int, 0644); diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/stv0297.c mp-bc1/linux/drivers/media/dvb/frontends/stv0297.c --- 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-17 23:45:43.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"); diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/stv0299.c mp-bc1/linux/drivers/media/dvb/frontends/stv0299.c --- v4l-dvb/linux/drivers/media/dvb/frontends/stv0299.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/stv0299.c 2006-07-17 23:45:47.000000000 +0400 @@ -130,7 +130,7 @@ static int stv0299_readregs (struct stv0 return ret == 2 ? 0 : ret; } -static int stv0299_set_FEC (struct stv0299_state* state, fe_code_rate_t fec) +static int stv0299_set_FEC_compat(struct stv0299_state* state, fe_code_rate_t fec) { dprintk ("%s\n", __FUNCTION__); @@ -166,7 +166,43 @@ static int stv0299_set_FEC (struct stv02 } } -static fe_code_rate_t stv0299_get_fec (struct stv0299_state* state) +static int stv0299_set_FEC(struct stv0299_state* state, enum dvbfe_fec fec) +{ + dprintk ("%s\n", __FUNCTION__); + + switch (fec) { + case DVBFE_FEC_AUTO: + { + return stv0299_writeregI (state, 0x31, 0x1f); + } + case DVBFE_FEC_1_2: + { + return stv0299_writeregI (state, 0x31, 0x01); + } + case DVBFE_FEC_2_3: + { + return stv0299_writeregI (state, 0x31, 0x02); + } + case DVBFE_FEC_3_4: + { + return stv0299_writeregI (state, 0x31, 0x04); + } + case DVBFE_FEC_5_6: + { + return stv0299_writeregI (state, 0x31, 0x08); + } + case DVBFE_FEC_7_8: + { + return stv0299_writeregI (state, 0x31, 0x10); + } + default: + { + return -EINVAL; + } + } +} + +static fe_code_rate_t stv0299_get_fec_compat(struct stv0299_state* state) { static fe_code_rate_t fec_tab [] = { FEC_2_3, FEC_3_4, FEC_5_6, FEC_7_8, FEC_1_2 }; @@ -183,6 +219,29 @@ static fe_code_rate_t stv0299_get_fec (s return fec_tab [index]; } +static fe_code_rate_t stv0299_get_fec(struct stv0299_state* state) +{ + static fe_code_rate_t fec_tab [] = { + DVBFE_FEC_2_3, + DVBFE_FEC_3_4, + DVBFE_FEC_5_6, + DVBFE_FEC_7_8, + DVBFE_FEC_1_2 + }; + + u8 index; + + dprintk ("%s\n", __FUNCTION__); + + index = stv0299_readreg (state, 0x1b); + index &= 0x7; + + if (index > 4) + return DVBFE_FEC_AUTO; + + return fec_tab[index]; +} + static int stv0299_wait_diseqc_fifo (struct stv0299_state* state, int timeout) { unsigned long start = jiffies; @@ -546,12 +605,13 @@ static int stv0299_set_frontend(struct d if (state->config->invert) invval = (~invval) & 1; stv0299_writeregI(state, 0x0c, (stv0299_readreg(state, 0x0c) & 0xfe) | invval); - 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); } - stv0299_set_FEC (state, p->u.qpsk.fec_inner); + stv0299_set_FEC_compat(state, p->u.qpsk.fec_inner); stv0299_set_symbolrate (fe, p->u.qpsk.symbol_rate); stv0299_writeregI(state, 0x22, 0x00); stv0299_writeregI(state, 0x23, 0x00); @@ -582,7 +642,7 @@ static int stv0299_get_frontend(struct d if (state->config->invert) invval = (~invval) & 1; p->inversion = invval ? INVERSION_ON : INVERSION_OFF; - p->u.qpsk.fec_inner = stv0299_get_fec (state); + p->u.qpsk.fec_inner = stv0299_get_fec_compat(state); p->u.qpsk.symbol_rate = stv0299_get_symbolrate (state); return 0; @@ -616,12 +676,24 @@ static int stv0299_get_tune_settings(str struct stv0299_state* state = fe->demodulator_priv; fesettings->min_delay_ms = state->config->min_delay_ms; - if (fesettings->parameters.u.qpsk.symbol_rate < 10000000) { - fesettings->step_size = fesettings->parameters.u.qpsk.symbol_rate / 32000; - fesettings->max_drift = 5000; + + if (fe->legacy) { + if (fesettings->parameters.u.qpsk.symbol_rate < 10000000) { + fesettings->step_size = fesettings->parameters.u.qpsk.symbol_rate / 32000; + fesettings->max_drift = 5000; + } else { + fesettings->step_size = fesettings->parameters.u.qpsk.symbol_rate / 16000; + fesettings->max_drift = fesettings->parameters.u.qpsk.symbol_rate / 2000; + } } else { - fesettings->step_size = fesettings->parameters.u.qpsk.symbol_rate / 16000; - fesettings->max_drift = fesettings->parameters.u.qpsk.symbol_rate / 2000; + if (fesettings->fe_params.delsys.dvbs.symbol_rate < 10000000) { + fesettings->step_size = fesettings->fe_params.delsys.dvbs.symbol_rate / 32000; + fesettings->max_drift = 5000; + } else { + fesettings->step_size = fesettings->fe_params.delsys.dvbs.symbol_rate / 16000; + fesettings->max_drift = fesettings->fe_params.delsys.dvbs.symbol_rate / 2000; + } + } return 0; } @@ -672,8 +744,107 @@ error: return NULL; } -static struct dvb_frontend_ops stv0299_ops = { +static int stv0299_set_params(struct dvb_frontend* fe, struct dvbfe_params *p) +{ + struct stv0299_state* state = fe->demodulator_priv; + int invval = 0; + + dprintk ("%s: Frequency=[%d] SymbolRate=[%d]\n", + __func__, p->frequency, p->delsys.dvbs.symbol_rate); + + // set the inversion + if (p->inversion == INVERSION_OFF) + invval = 0; + else if (p->inversion == INVERSION_ON) + invval = 1; + else { + printk("stv0299 does not support auto-inversion\n"); + return -EINVAL; + } + if (state->config->invert) + invval = (~invval) & 1; + stv0299_writeregI(state, 0x0c, (stv0299_readreg(state, 0x0c) & 0xfe) | invval); + + 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); + } + + stv0299_set_FEC(state, p->delsys.dvbs.fec); + stv0299_set_symbolrate(fe, p->delsys.dvbs.symbol_rate); + stv0299_writeregI(state, 0x22, 0x00); + stv0299_writeregI(state, 0x23, 0x00); + + state->tuner_frequency = p->frequency; + state->fec_inner = p->delsys.dvbs.fec; + state->symbol_rate = p->delsys.dvbs.symbol_rate; + + return 0; +} + +static int stv0299_get_params(struct dvb_frontend* fe, struct dvbfe_params *p) +{ + struct stv0299_state* state = fe->demodulator_priv; + s32 derot_freq; + int invval; + derot_freq = (s32)(s16) ((stv0299_readreg (state, 0x22) << 8) + | stv0299_readreg (state, 0x23)); + + derot_freq *= (state->config->mclk >> 16); + derot_freq += 500; + derot_freq /= 1000; + + p->frequency += derot_freq; + + invval = stv0299_readreg(state, 0x0c) & 1; + if (state->config->invert) + invval = (~invval) & 1; + p->inversion = invval ? INVERSION_ON : INVERSION_OFF; + + p->delsys.dvbs.fec = stv0299_get_fec(state); + p->delsys.dvbs.symbol_rate = stv0299_get_symbolrate(state); + + return 0; +} + + +static struct dvbfe_info dvbs_info = { + .name = "STV0299 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 = 125, + .frequency_tolerance = 0, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + .symbol_rate_tolerance = 500 +}; + +static int stv0299_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info) +{ + memcpy(fe_info, &dvbs_info, sizeof (dvbs_info)); + + return 0; +} + +static int stv0299_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_DVBS; + + return 0; +} + +static struct dvb_frontend_ops stv0299_ops = { + /* Info is deprecated */ .info = { .name = "ST STV0299 DVB-S", .type = FE_QPSK, @@ -711,6 +882,11 @@ static struct dvb_frontend_ops stv0299_o .set_tone = stv0299_set_tone, .set_voltage = stv0299_set_voltage, .dishnetwork_send_legacy_command = stv0299_send_legacy_dish_cmd, + + .set_params = stv0299_set_params, + .get_params = stv0299_get_params, + .get_info = stv0299_get_info, + .get_delsys = stv0299_get_delsys, }; module_param(debug_legacy_dish_switch, int, 0444); diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/tda10021.c mp-bc1/linux/drivers/media/dvb/frontends/tda10021.c --- v4l-dvb/linux/drivers/media/dvb/frontends/tda10021.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/tda10021.c 2006-07-17 23:45:56.000000000 +0400 @@ -259,9 +259,10 @@ static int tda10021_set_parameters (stru //printk("tda10021: set frequency to %d qam=%d symrate=%d\n", p->frequency,qam,p->u.qam.symbol_rate); - 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); } tda10021_set_symbolrate (state, p->u.qam.symbol_rate); @@ -436,6 +437,130 @@ error: return NULL; } +static struct dvbfe_info dvbc_info = { + .name = "Philips TDA10021 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 = 51000000, + .frequency_max = 858000000, + .symbol_rate_min = (XIN / 2) / 64, + .symbol_rate_max = (XIN / 2) / 4, +}; + +static int tda10021_set_params(struct dvb_frontend *fe, + struct dvbfe_params *p) +{ + struct tda10021_state* state = fe->demodulator_priv; + + //table for QAM4-QAM256 ready QAM4 QAM16 QAM32 QAM64 QAM128 QAM256 + //CONF + static const u8 reg0x00 [] = { 0x14, 0x00, 0x04, 0x08, 0x0c, 0x10 }; + //AGCREF value + static const u8 reg0x01 [] = { 0x78, 0x8c, 0x8c, 0x6a, 0x78, 0x5c }; + //LTHR value + static const u8 reg0x05 [] = { 0x78, 0x87, 0x64, 0x46, 0x36, 0x26 }; + //MSETH + static const u8 reg0x08 [] = { 0x8c, 0xa2, 0x74, 0x43, 0x34, 0x23 }; + //AREF + static const u8 reg0x09 [] = { 0x96, 0x91, 0x96, 0x6a, 0x7e, 0x6b }; + + int qam = p->delsys.dvbc.modulation; + +// if (qam < 0 || qam > 5) +// return -EINVAL; + + //printk("tda10021: set frequency to %d qam=%d symrate=%d\n", p->frequency,qam,p->u.qam.symbol_rate); + + 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); + } + + tda10021_set_symbolrate(state, p->delsys.dvbc.symbol_rate); + tda10021_writereg(state, 0x34, state->pwm); + + tda10021_writereg(state, 0x01, reg0x01[fls(qam) - fls(DVBFE_MOD_QAM4)]); + tda10021_writereg(state, 0x05, reg0x05[fls(qam) - fls(DVBFE_MOD_QAM4)]); + tda10021_writereg(state, 0x08, reg0x08[fls(qam) - fls(DVBFE_MOD_QAM4)]); + tda10021_writereg(state, 0x09, reg0x09[fls(qam) - fls(DVBFE_MOD_QAM4)]); + + tda10021_setup_reg0(state, reg0x00[qam], p->inversion); + + return 0; +} + +static int tda10021_get_params(struct dvb_frontend* fe, struct dvbfe_params *p) +{ + struct tda10021_state* state = fe->demodulator_priv; + int sync; + s8 afc = 0; + u32 mod; + + sync = tda10021_readreg(state, 0x11); + afc = tda10021_readreg(state, 0x19); + if (verbose) { + /* AFC only valid when carrier has been recovered */ + printk(sync & 2 ? "DVB: TDA10021(%d): AFC (%d) %dHz\n" : + "DVB: TDA10021(%d): [AFC (%d) %dHz]\n", + state->frontend.dvb->num, afc, + -((s32)p->delsys.dvbc.symbol_rate * afc) >> 10); + } + + p->inversion = HAS_INVERSION(state->reg0) ? INVERSION_ON : INVERSION_OFF; + mod = ((state->reg0 >> 2) & 7); + switch (mod) { + 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_QAM64; + break; + case 3: + case 7: + p->delsys.dvbc.modulation = DVBFE_MOD_QAM128; + break; + case 4: + p->delsys.dvbc.modulation = DVBFE_MOD_QAM256; + break; + case 5: + p->delsys.dvbc.modulation = DVBFE_MOD_QAM4; + break; + default: + break; + } + + p->delsys.dvbc.fec = DVBFE_FEC_NONE; + p->frequency = ((p->frequency + 31250) / 62500) * 62500; + + if (sync & 2) + p->frequency -= ((s32)p->delsys.dvbc.symbol_rate * afc) >> 10; + + return 0; +} + +static int tda10021_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info) +{ + memcpy(fe_info, &dvbc_info, sizeof (dvbc_info)); + + return 0; +} + +static int tda10021_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_DVBC; + + return 0; +} + static struct dvb_frontend_ops tda10021_ops = { .info = { @@ -470,6 +595,11 @@ static struct dvb_frontend_ops tda10021_ .read_signal_strength = tda10021_read_signal_strength, .read_snr = tda10021_read_snr, .read_ucblocks = tda10021_read_ucblocks, + + .set_params = tda10021_set_params, + .get_params = tda10021_get_params, + .get_info = tda10021_get_info, + .get_delsys = tda10021_get_delsys, }; module_param(verbose, int, 0644); diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/tda1004x.c mp-bc1/linux/drivers/media/dvb/frontends/tda1004x.c --- v4l-dvb/linux/drivers/media/dvb/frontends/tda1004x.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/tda1004x.c 2006-07-17 23:46:03.000000000 +0400 @@ -238,8 +238,8 @@ static int tda1004x_disable_tuner_i2c(st return tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 0); } -static int tda10045h_set_bandwidth(struct tda1004x_state *state, - fe_bandwidth_t bandwidth) +static int tda10045h_set_bandwidth_compat(struct tda1004x_state *state, + fe_bandwidth_t bandwidth) { static u8 bandwidth_6mhz[] = { 0x02, 0x00, 0x3d, 0x00, 0x60, 0x1e, 0xa7, 0x45, 0x4f }; static u8 bandwidth_7mhz[] = { 0x02, 0x00, 0x37, 0x00, 0x4a, 0x2f, 0x6d, 0x76, 0xdb }; @@ -267,8 +267,37 @@ static int tda10045h_set_bandwidth(struc return 0; } -static int tda10046h_set_bandwidth(struct tda1004x_state *state, - fe_bandwidth_t bandwidth) +static int tda10045h_set_bandwidth(struct tda1004x_state *state, + enum dvbfe_bandwidth bandwidth) +{ + static u8 bandwidth_6mhz[] = { 0x02, 0x00, 0x3d, 0x00, 0x60, 0x1e, 0xa7, 0x45, 0x4f }; + static u8 bandwidth_7mhz[] = { 0x02, 0x00, 0x37, 0x00, 0x4a, 0x2f, 0x6d, 0x76, 0xdb }; + static u8 bandwidth_8mhz[] = { 0x02, 0x00, 0x3d, 0x00, 0x48, 0x17, 0x89, 0xc7, 0x14 }; + + switch (bandwidth) { + case DVBFE_BANDWIDTH_6_MHZ: + tda1004x_write_buf(state, TDA10045H_CONFPLL_P, bandwidth_6mhz, sizeof(bandwidth_6mhz)); + break; + + case DVBFE_BANDWIDTH_7_MHZ: + tda1004x_write_buf(state, TDA10045H_CONFPLL_P, bandwidth_7mhz, sizeof(bandwidth_7mhz)); + break; + + case DVBFE_BANDWIDTH_8_MHZ: + tda1004x_write_buf(state, TDA10045H_CONFPLL_P, bandwidth_8mhz, sizeof(bandwidth_8mhz)); + break; + + default: + return -EINVAL; + } + + tda1004x_write_byteI(state, TDA10045H_IOFFSET, 0); + + return 0; +} + +static int tda10046h_set_bandwidth_compat(struct tda1004x_state *state, + fe_bandwidth_t bandwidth) { static u8 bandwidth_6mhz_53M[] = { 0x7b, 0x2e, 0x11, 0xf0, 0xd2 }; static u8 bandwidth_7mhz_53M[] = { 0x6a, 0x02, 0x6a, 0x43, 0x9f }; @@ -331,6 +360,70 @@ static int tda10046h_set_bandwidth(struc return 0; } +static int tda10046h_set_bandwidth(struct tda1004x_state *state, + enum dvbfe_bandwidth bandwidth) +{ + static u8 bandwidth_6mhz_53M[] = { 0x7b, 0x2e, 0x11, 0xf0, 0xd2 }; + static u8 bandwidth_7mhz_53M[] = { 0x6a, 0x02, 0x6a, 0x43, 0x9f }; + static u8 bandwidth_8mhz_53M[] = { 0x5c, 0x32, 0xc2, 0x96, 0x6d }; + + static u8 bandwidth_6mhz_48M[] = { 0x70, 0x02, 0x49, 0x24, 0x92 }; + static u8 bandwidth_7mhz_48M[] = { 0x60, 0x02, 0xaa, 0xaa, 0xab }; + static u8 bandwidth_8mhz_48M[] = { 0x54, 0x03, 0x0c, 0x30, 0xc3 }; + int tda10046_clk53m; + + if ((state->config->if_freq == TDA10046_FREQ_045) || + (state->config->if_freq == TDA10046_FREQ_052)) + tda10046_clk53m = 0; + else + tda10046_clk53m = 1; + switch (bandwidth) { + case DVBFE_BANDWIDTH_6_MHZ: + if (tda10046_clk53m) + tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz_53M, + sizeof(bandwidth_6mhz_53M)); + else + tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz_48M, + sizeof(bandwidth_6mhz_48M)); + if (state->config->if_freq == TDA10046_FREQ_045) { + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0a); + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xab); + } + break; + + case DVBFE_BANDWIDTH_7_MHZ: + if (tda10046_clk53m) + tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz_53M, + sizeof(bandwidth_7mhz_53M)); + else + tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz_48M, + sizeof(bandwidth_7mhz_48M)); + if (state->config->if_freq == TDA10046_FREQ_045) { + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c); + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x00); + } + break; + + case DVBFE_BANDWIDTH_8_MHZ: + if (tda10046_clk53m) + tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz_53M, + sizeof(bandwidth_8mhz_53M)); + else + tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz_48M, + sizeof(bandwidth_8mhz_48M)); + if (state->config->if_freq == TDA10046_FREQ_045) { + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0d); + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x55); + } + break; + + default: + return -EINVAL; + } + + return 0; +} + static int tda1004x_do_upload(struct tda1004x_state *state, unsigned char *mem, unsigned int len, u8 dspCodeCounterReg, u8 dspCodeInReg) @@ -424,7 +517,10 @@ static int tda10045_fwupload(struct dvb_ msleep(10); /* set parameters */ - tda10045h_set_bandwidth(state, BANDWIDTH_8_MHZ); + if (fe->legacy) + tda10045h_set_bandwidth_compat(state, BANDWIDTH_8_MHZ); + else + tda10045h_set_bandwidth(state, DVBFE_BANDWIDTH_8_MHZ); ret = tda1004x_do_upload(state, fw->data, fw->size, TDA10045H_FWPAGE, TDA10045H_CODE_IN); release_firmware(fw); @@ -488,7 +584,10 @@ static void tda10046_init_plls(struct dv tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x3f); break; } - tda10046h_set_bandwidth(state, BANDWIDTH_8_MHZ); // default bandwidth 8 MHz + if (fe->legacy) + tda10046h_set_bandwidth_compat(state, BANDWIDTH_8_MHZ); // default bandwidth 8 MHz + else + tda10046h_set_bandwidth(state, DVBFE_BANDWIDTH_8_MHZ); // default bandwidth 8 MHz /* let the PLLs settle */ msleep(120); } @@ -694,9 +793,10 @@ static int tda1004x_set_fe(struct dvb_fr } // set frequency - if (fe->ops.tuner_ops.set_params) { - fe->ops.tuner_ops.set_params(fe, fe_params); - 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, fe_params); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); } // Hardcoded to use auto as much as possible on the TDA10045 as it @@ -775,11 +875,11 @@ static int tda1004x_set_fe(struct dvb_fr // set bandwidth switch (state->demod_type) { case TDA1004X_DEMOD_TDA10045: - tda10045h_set_bandwidth(state, fe_params->u.ofdm.bandwidth); + tda10045h_set_bandwidth_compat(state, fe_params->u.ofdm.bandwidth); break; case TDA1004X_DEMOD_TDA10046: - tda10046h_set_bandwidth(state, fe_params->u.ofdm.bandwidth); + tda10046h_set_bandwidth_compat(state, fe_params->u.ofdm.bandwidth); break; } @@ -871,6 +971,208 @@ static int tda1004x_set_fe(struct dvb_fr return 0; } +static int tda1004x_set_params(struct dvb_frontend* fe, + struct dvbfe_params *fe_params) +{ + struct tda1004x_state* state = fe->demodulator_priv; + int tmp; + int inversion; + + dprintk("%s\n", __FUNCTION__); + + if (state->demod_type == TDA1004X_DEMOD_TDA10046) { + // setup auto offset + tda1004x_write_mask(state, TDA1004X_AUTO, 0x10, 0x10); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x80, 0); + tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0xC0, 0); + + // disable agc_conf[2] + tda1004x_write_mask(state, TDA10046H_AGC_CONF, 4, 0); + } + + // set frequency + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, fe_params); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + } + + // Hardcoded to use auto as much as possible on the TDA10045 as it + // is very unreliable if AUTO mode is _not_ used. + if (state->demod_type == TDA1004X_DEMOD_TDA10045) { + fe_params->delsys.dvbt.code_rate_HP = DVBFE_FEC_AUTO; + fe_params->delsys.dvbt.guard_interval = DVBFE_GUARD_INTERVAL_AUTO; + fe_params->delsys.dvbt.transmission_mode = DVBFE_TRANSMISSION_MODE_AUTO; + } + + // Set standard params.. or put them to auto + if ((fe_params->delsys.dvbt.code_rate_HP == DVBFE_FEC_AUTO) || + (fe_params->delsys.dvbt.code_rate_LP == DVBFE_FEC_AUTO) || + (fe_params->delsys.dvbt.constellation == DVBFE_MOD_QAMAUTO) || + (fe_params->delsys.dvbt.hierarchy == DVBFE_HIERARCHY_AUTO)) { + + tda1004x_write_mask(state, TDA1004X_AUTO, 1, 1); // enable auto + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x03, 0); // turn off constellation bits + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 0); // turn off hierarchy bits + tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0x3f, 0); // turn off FEC bits + } else { + tda1004x_write_mask(state, TDA1004X_AUTO, 1, 0); // disable auto + + // set HP FEC + tmp = tda1004x_encode_fec(fe_params->delsys.dvbt.code_rate_HP); + if (tmp < 0) + return tmp; + tda1004x_write_mask(state, TDA1004X_IN_CONF2, 7, tmp); + + // set LP FEC + tmp = tda1004x_encode_fec(fe_params->delsys.dvbt.code_rate_LP); + if (tmp < 0) + return tmp; + tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0x38, tmp << 3); + + // set constellation + switch (fe_params->delsys.dvbt.constellation) { + case DVBFE_MOD_QPSK: + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 3, 0); + break; + + case DVBFE_MOD_QAM16: + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 3, 1); + break; + + case DVBFE_MOD_QAM64: + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 3, 2); + break; + + default: + return -EINVAL; + } + + // set hierarchy + switch (fe_params->delsys.dvbt.hierarchy) { + case DVBFE_HIERARCHY_OFF: + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 0 << 5); + break; + + case DVBFE_HIERARCHY_ON: + switch (fe_params->delsys.dvbt.alpha) { + case DVBFE_ALPHA_1: + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 1 << 5); + break; + + case DVBFE_ALPHA_2: + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 2 << 5); + break; + + case DVBFE_ALPHA_4: + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 3 << 5); + break; + } + break; + default: + return -EINVAL; + } + } + + // set bandwidth + switch (state->demod_type) { + case TDA1004X_DEMOD_TDA10045: + tda10045h_set_bandwidth(state, fe_params->delsys.dvbt.bandwidth); + break; + + case TDA1004X_DEMOD_TDA10046: + tda10046h_set_bandwidth(state, fe_params->delsys.dvbt.bandwidth); + break; + } + + // set inversion + inversion = fe_params->inversion; + if (state->config->invert) + inversion = inversion ? INVERSION_OFF : INVERSION_ON; + switch (inversion) { + case INVERSION_OFF: + tda1004x_write_mask(state, TDA1004X_CONFC1, 0x20, 0); + break; + + case INVERSION_ON: + tda1004x_write_mask(state, TDA1004X_CONFC1, 0x20, 0x20); + break; + + default: + return -EINVAL; + } + + // set guard interval + switch (fe_params->delsys.dvbt.guard_interval) { + case DVBFE_GUARD_INTERVAL_1_32: + tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 0 << 2); + break; + + case DVBFE_GUARD_INTERVAL_1_16: + tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 1 << 2); + break; + + case DVBFE_GUARD_INTERVAL_1_8: + tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 2 << 2); + break; + + case DVBFE_GUARD_INTERVAL_1_4: + tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 3 << 2); + break; + + case DVBFE_GUARD_INTERVAL_AUTO: + tda1004x_write_mask(state, TDA1004X_AUTO, 2, 2); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 0 << 2); + break; + + default: + return -EINVAL; + } + + // set transmission mode + switch (fe_params->delsys.dvbt.transmission_mode) { + case DVBFE_TRANSMISSION_MODE_2K: + tda1004x_write_mask(state, TDA1004X_AUTO, 4, 0); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x10, 0 << 4); + break; + + case DVBFE_TRANSMISSION_MODE_8K: + tda1004x_write_mask(state, TDA1004X_AUTO, 4, 0); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x10, 1 << 4); + break; + + case DVBFE_TRANSMISSION_MODE_AUTO: + tda1004x_write_mask(state, TDA1004X_AUTO, 4, 4); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x10, 0); + break; + + default: + return -EINVAL; + } + + // start the lock + switch (state->demod_type) { + case TDA1004X_DEMOD_TDA10045: + tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8); + tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 0); + break; + + case TDA1004X_DEMOD_TDA10046: + tda1004x_write_mask(state, TDA1004X_AUTO, 0x40, 0x40); + msleep(1); + tda1004x_write_mask(state, TDA10046H_AGC_CONF, 4, 1); + break; + } + + msleep(10); + + return 0; +} + static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_parameters *fe_params) { struct tda1004x_state* state = fe->demodulator_priv; @@ -976,6 +1278,114 @@ static int tda1004x_get_fe(struct dvb_fr return 0; } +static int tda1004x_get_params(struct dvb_frontend* fe, struct dvbfe_params *fe_params) +{ + struct tda1004x_state* state = fe->demodulator_priv; + + dprintk("%s\n", __FUNCTION__); + + // inversion status + fe_params->inversion = INVERSION_OFF; + if (tda1004x_read_byte(state, TDA1004X_CONFC1) & 0x20) + fe_params->inversion = INVERSION_ON; + if (state->config->invert) + fe_params->inversion = fe_params->inversion ? INVERSION_OFF : INVERSION_ON; + + // bandwidth + switch (state->demod_type) { + case TDA1004X_DEMOD_TDA10045: + switch (tda1004x_read_byte(state, TDA10045H_WREF_LSB)) { + case 0x14: + fe_params->delsys.dvbt.bandwidth = DVBFE_BANDWIDTH_8_MHZ; + break; + case 0xdb: + fe_params->delsys.dvbt.bandwidth = DVBFE_BANDWIDTH_7_MHZ; + break; + case 0x4f: + fe_params->delsys.dvbt.bandwidth = DVBFE_BANDWIDTH_6_MHZ; + break; + } + break; + case TDA1004X_DEMOD_TDA10046: + switch (tda1004x_read_byte(state, TDA10046H_TIME_WREF1)) { + case 0x5c: + case 0x54: + fe_params->delsys.dvbt.bandwidth = DVBFE_BANDWIDTH_8_MHZ; + break; + case 0x6a: + case 0x60: + fe_params->delsys.dvbt.bandwidth = DVBFE_BANDWIDTH_7_MHZ; + break; + case 0x7b: + case 0x70: + fe_params->delsys.dvbt.bandwidth = DVBFE_BANDWIDTH_6_MHZ; + break; + } + break; + } + + // FEC + fe_params->delsys.dvbt.code_rate_HP = + tda1004x_decode_fec(tda1004x_read_byte(state, TDA1004X_OUT_CONF2) & 7); + fe_params->delsys.dvbt.code_rate_LP = + tda1004x_decode_fec((tda1004x_read_byte(state, TDA1004X_OUT_CONF2) >> 3) & 7); + + // constellation + switch (tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 3) { + case 0: + fe_params->delsys.dvbt.constellation = DVBFE_MOD_QPSK; + break; + case 1: + fe_params->delsys.dvbt.constellation = DVBFE_MOD_QAM16; + break; + case 2: + fe_params->delsys.dvbt.constellation = DVBFE_MOD_QAM64; + break; + } + + // transmission mode + fe_params->delsys.dvbt.transmission_mode = DVBFE_TRANSMISSION_MODE_2K; + if (tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x10) + fe_params->delsys.dvbt.transmission_mode = DVBFE_TRANSMISSION_MODE_8K; + + // guard interval + switch ((tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x0c) >> 2) { + case 0: + fe_params->delsys.dvbt.guard_interval = DVBFE_GUARD_INTERVAL_1_32; + break; + case 1: + fe_params->delsys.dvbt.guard_interval = DVBFE_GUARD_INTERVAL_1_16; + break; + case 2: + fe_params->delsys.dvbt.guard_interval = DVBFE_GUARD_INTERVAL_1_8; + break; + case 3: + fe_params->delsys.dvbt.guard_interval = DVBFE_GUARD_INTERVAL_1_4; + break; + } + + // hierarchy + switch ((tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x60) >> 5) { + case 0: + fe_params->delsys.dvbt.hierarchy = DVBFE_HIERARCHY_OFF; + break; + case 1: + fe_params->delsys.dvbt.hierarchy = DVBFE_HIERARCHY_ON; + fe_params->delsys.dvbt.alpha = DVBFE_ALPHA_1; + break; + case 2: + fe_params->delsys.dvbt.hierarchy = DVBFE_HIERARCHY_ON; + fe_params->delsys.dvbt.alpha = DVBFE_ALPHA_2; + break; + case 3: + fe_params->delsys.dvbt.hierarchy = DVBFE_HIERARCHY_ON; + fe_params->delsys.dvbt.alpha = DVBFE_ALPHA_4; + break; + } + + return 0; +} + static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status) { struct tda1004x_state* state = fe->demodulator_priv; @@ -1256,6 +1666,57 @@ struct dvb_frontend* tda10045_attach(con return &state->frontend; } +static struct dvbfe_info tda10045_info = { + .name = "Philips TDA10045 DVB-T", + .delivery = DVBFE_DELSYS_DVBT, + .delsys = { + .dvbt.modulation = DVBFE_MOD_OFDM, + .dvbt.stream_priority = DVBFE_STREAM_PRIORITY_HP | + DVBFE_STREAM_PRIORITY_LP + }, + + .frequency_min = 51000000, + .frequency_max = 858000000, + .frequency_step = 166667, +}; + +static struct dvbfe_info tda10046_info = { + .name = "Philips TDA10046 DVB-T", + .delivery = DVBFE_DELSYS_DVBT, + .delsys = { + .dvbt.modulation = DVBFE_MOD_OFDM, + .dvbt.stream_priority = DVBFE_STREAM_PRIORITY_HP | + DVBFE_STREAM_PRIORITY_LP + }, + + .frequency_min = 51000000, + .frequency_max = 858000000, + .frequency_step = 166667, +}; + +static int tda1004x_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info) +{ + struct tda1004x_state *state = fe->demodulator_priv; + + switch (state->demod_type) { + case TDA1004X_DEMOD_TDA10045: + memcpy(fe_info, &tda10045_info, sizeof (tda10045_info)); + break; + case TDA1004X_DEMOD_TDA10046: + memcpy(fe_info, &tda10046_info, sizeof (tda10046_info)); + break; + } + + return 0; +} + +static int tda1004x_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_DVBT; + + return 0; +} + static struct dvb_frontend_ops tda10046_ops = { .info = { .name = "Philips TDA10046H DVB-T", @@ -1285,6 +1746,11 @@ static struct dvb_frontend_ops tda10046_ .read_signal_strength = tda1004x_read_signal_strength, .read_snr = tda1004x_read_snr, .read_ucblocks = tda1004x_read_ucblocks, + + .set_params = tda1004x_set_params, + .get_params = tda1004x_get_params, + .get_info = tda1004x_get_info, + .get_delsys = tda1004x_get_delsys, }; struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config, diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/tda8083.c mp-bc1/linux/drivers/media/dvb/frontends/tda8083.c --- v4l-dvb/linux/drivers/media/dvb/frontends/tda8083.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/tda8083.c 2006-07-17 23:46:09.000000000 +0400 @@ -107,7 +107,7 @@ static int tda8083_set_inversion (struct return -EINVAL; } -static int tda8083_set_fec (struct tda8083_state* state, fe_code_rate_t fec) +static int tda8083_set_fec_compat(struct tda8083_state* state, fe_code_rate_t fec) { if (fec == FEC_AUTO) return tda8083_writereg (state, 0x07, 0xff); @@ -118,7 +118,29 @@ static int tda8083_set_fec (struct tda80 return -EINVAL; } -static fe_code_rate_t tda8083_get_fec (struct tda8083_state* state) +static int tda8083_set_fec(struct tda8083_state* state, enum dvbfe_fec fec) +{ + switch (fec) { + case DVBFE_FEC_AUTO: + return tda8083_writereg(state, 0x07, 0xff); + case DVBFE_FEC_1_2: + return tda8083_writereg(state, 0x07, (1 << 7)); + case DVBFE_FEC_2_3: + return tda8083_writereg(state, 0x07, (1 << 6)); + case DVBFE_FEC_3_4: + return tda8083_writereg(state, 0x07, (1 << 5)); + case DVBFE_FEC_5_6: + return tda8083_writereg(state, 0x07, (1 << 4)); + case DVBFE_FEC_7_8: + return tda8083_writereg(state, 0x07, (1 << 1)); + default: + return -EINVAL; + } + + return 0; +} + +static fe_code_rate_t tda8083_get_fec_compat(struct tda8083_state* state) { u8 index; static fe_code_rate_t fec_tab [] = { FEC_8_9, FEC_1_2, FEC_2_3, FEC_3_4, @@ -129,6 +151,26 @@ static fe_code_rate_t tda8083_get_fec (s return fec_tab [index]; } +static fe_code_rate_t tda8083_get_fec(struct tda8083_state* state) +{ + u8 index; + + enum dvbfe_fec fec_tab [] = { + DVBFE_FEC_8_9, + DVBFE_FEC_1_2, + DVBFE_FEC_2_3, + DVBFE_FEC_3_4, + DVBFE_FEC_4_5, + DVBFE_FEC_5_6, + DVBFE_FEC_6_7, + DVBFE_FEC_7_8 + }; + + index = tda8083_readreg(state, 0x0e) & 0x07; + + return fec_tab[index]; +} + static int tda8083_set_symbolrate (struct tda8083_state* state, u32 srate) { u32 ratio; @@ -292,13 +334,14 @@ static int tda8083_set_frontend(struct d { struct tda8083_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); } - tda8083_set_inversion (state, p->inversion); - tda8083_set_fec (state, p->u.qpsk.fec_inner); + tda8083_set_inversion(state, p->inversion); + tda8083_set_fec_compat(state, p->u.qpsk.fec_inner); tda8083_set_symbolrate (state, p->u.qpsk.symbol_rate); tda8083_writereg (state, 0x00, 0x3c); @@ -307,7 +350,29 @@ static int tda8083_set_frontend(struct d return 0; } -static int tda8083_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) +static int tda8083_set_params(struct dvb_frontend* fe, + struct dvbfe_params *p) +{ + struct tda8083_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); + } + + tda8083_set_inversion(state, p->inversion); + tda8083_set_fec(state, p->delsys.dvbs.fec); + tda8083_set_symbolrate(state, p->delsys.dvbs.symbol_rate); + + tda8083_writereg(state, 0x00, 0x3c); + tda8083_writereg(state, 0x00, 0x04); + + return 0; +} + +static int tda8083_get_frontend(struct dvb_frontend* fe, + struct dvb_frontend_parameters *p) { struct tda8083_state* state = fe->demodulator_priv; @@ -315,7 +380,22 @@ static int tda8083_get_frontend(struct d /*p->frequency = ???;*/ p->inversion = (tda8083_readreg (state, 0x0e) & 0x80) ? INVERSION_ON : INVERSION_OFF; - p->u.qpsk.fec_inner = tda8083_get_fec (state); + p->u.qpsk.fec_inner = tda8083_get_fec_compat(state); + /*p->u.qpsk.symbol_rate = tda8083_get_symbolrate (state);*/ + + return 0; +} + +static int tda8083_get_params(struct dvb_frontend* fe, + struct dvbfe_params *p) +{ + struct tda8083_state* state = fe->demodulator_priv; + + /* FIXME: get symbolrate & frequency offset...*/ + /*p->frequency = ???;*/ + p->inversion = (tda8083_readreg (state, 0x0e) & 0x80) ? + INVERSION_ON : INVERSION_OFF; + p->delsys.dvbs.fec = tda8083_get_fec(state); /*p->u.qpsk.symbol_rate = tda8083_get_symbolrate (state);*/ return 0; @@ -410,6 +490,37 @@ error: return NULL; } +static struct dvbfe_info dvbs_info = { + .name = "Philips TDA8083 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 = 1400000, + .frequency_step = 125, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, +}; + +static int tda8083_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info) +{ + memcpy(fe_info, &dvbs_info, sizeof (dvbs_info)); + + return 0; +} + +static int tda8083_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_DVBS; + + return 0; +} + static struct dvb_frontend_ops tda8083_ops = { .info = { @@ -445,6 +556,11 @@ static struct dvb_frontend_ops tda8083_o .diseqc_send_burst = tda8083_diseqc_send_burst, .set_tone = tda8083_diseqc_set_tone, .set_voltage = tda8083_diseqc_set_voltage, + + .set_params = tda8083_set_params, + .get_params = tda8083_get_params, + .get_info = tda8083_get_info, + .get_delsys = tda8083_get_delsys, }; module_param(debug, int, 0644); diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/tda80xx.c mp-bc1/linux/drivers/media/dvb/frontends/tda80xx.c --- v4l-dvb/linux/drivers/media/dvb/frontends/tda80xx.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/tda80xx.c 2006-07-17 23:46:14.000000000 +0400 @@ -157,10 +157,10 @@ static __inline__ int tda80xx_writereg(s return tda80xx_write(state, reg, &data, 1); } -static int tda80xx_set_parameters(struct tda80xx_state* state, - fe_spectral_inversion_t inversion, - u32 symbol_rate, - fe_code_rate_t fec_inner) +static int tda80xx_set_parameters_compat(struct tda80xx_state* state, + fe_spectral_inversion_t inversion, + u32 symbol_rate, + fe_code_rate_t fec_inner) { u8 buf[15]; u64 ratio; @@ -287,6 +287,166 @@ static int tda80xx_set_parameters(struct return tda80xx_write(state, 0x01, buf, sizeof(buf)); } +static int tda80xx_set_parameters(struct tda80xx_state* state, + fe_spectral_inversion_t inversion, + u32 symbol_rate, + enum dvbfe_fec fec) +{ + u8 buf[15]; + u64 ratio; + u32 clk; + u32 k; + u32 sr = symbol_rate; + u32 gcd; + u8 scd; + + if (symbol_rate > (state->clk * 3) / 16) + scd = 0; + else if (symbol_rate > (state->clk * 3) / 32) + scd = 1; + else if (symbol_rate > (state->clk * 3) / 64) + scd = 2; + else + scd = 3; + + clk = scd ? (state->clk / (scd * 2)) : state->clk; + + /* + * Viterbi decoder: + * Differential decoding off + * Spectral inversion unknown + * QPSK modulation + */ + if (inversion == INVERSION_ON) + buf[0] = 0x60; + else if (inversion == INVERSION_OFF) + buf[0] = 0x20; + else + buf[0] = 0x00; + + /* + * CLK ratio: + * system clock frequency is up to 64 or 96 MHz + * + * formula: + * r = k * clk / symbol_rate + * + * k: 2^21 for caa 0..3, + * 2^20 for caa 4..5, + * 2^19 for caa 6..7 + */ + if (symbol_rate <= (clk * 3) / 32) + k = (1 << 19); + else if (symbol_rate <= (clk * 3) / 16) + k = (1 << 20); + else + k = (1 << 21); + + gcd = tda80xx_gcd(clk, sr); + clk /= gcd; + sr /= gcd; + + gcd = tda80xx_gcd(k, sr); + k /= gcd; + sr /= gcd; + + ratio = (u64)k * (u64)clk; + do_div(ratio, sr); + + buf[1] = ratio >> 16; + buf[2] = ratio >> 8; + buf[3] = ratio; + + /* nyquist filter roll-off factor 35% */ + buf[4] = 0x20; + + clk = scd ? (state->clk / (scd * 2)) : state->clk; + + /* Anti Alias Filter */ + if (symbol_rate < (clk * 3) / 64) + printk("tda80xx: unsupported symbol rate: %u\n", symbol_rate); + else if (symbol_rate <= clk / 16) + buf[4] |= 0x07; + else if (symbol_rate <= (clk * 3) / 32) + buf[4] |= 0x06; + else if (symbol_rate <= clk / 8) + buf[4] |= 0x05; + else if (symbol_rate <= (clk * 3) / 16) + buf[4] |= 0x04; + else if (symbol_rate <= clk / 4) + buf[4] |= 0x03; + else if (symbol_rate <= (clk * 3) / 8) + buf[4] |= 0x02; + else if (symbol_rate <= clk / 2) + buf[4] |= 0x01; + else + buf[4] |= 0x00; + + /* Sigma Delta converter */ + buf[5] = 0x00; + + /* FEC: Possible puncturing rates */ + if (fec == DVBFE_FEC_NONE) + buf[6] = 0x00; + else if ((fec >= DVBFE_FEC_1_2) && (fec_inner <= FEC_8_9)) + buf[6] = (1 << (8 - fec_inner)); + else if (fec_inner == FEC_AUTO) + buf[6] = 0xff; + else + return -EINVAL; + + switch (fec) { + case DVBFE_FEC_NONE: + buf[6] = 0x00; + break; + case DVBFE_FEC_1_2: + buf[6] = 1 << 7; + break; + case DVBFE_FEC_2_3: + buf[6] = 1 << 6; + break; + case DVBFE_FEC_3_4: + buf[6] = 1 << 5; + break; + case DVBFE_FEC_4_5: + buf[6] = 1 << 4; + break; + case DVBFE_FEC_5_6: + buf[6] = 1 << 3; + break; + case DVBFE_FEC_6_7: + buf[6] = 1 << 2; + break; + case DVBFE_FEC_7_8: + buf[6] = 1 << 1; + break; + case DVBFE_FEC_8_9: + buf[6] = 1 << 0; + break; + } + + /* carrier lock detector threshold value */ + buf[7] = 0x30; + /* AFC1: proportional part settings */ + buf[8] = 0x42; + /* AFC1: integral part settings */ + buf[9] = 0x98; + /* PD: Leaky integrator SCPC mode */ + buf[10] = 0x28; + /* AFC2, AFC1 controls */ + buf[11] = 0x30; + /* PD: proportional part settings */ + buf[12] = 0x42; + /* PD: integral part settings */ + buf[13] = 0x99; + /* AGC */ + buf[14] = 0x50 | scd; + + printk("symbol_rate=%u clk=%u\n", symbol_rate, clk); + + return tda80xx_write(state, 0x01, buf, sizeof (buf)); +} + static int tda80xx_set_clk(struct tda80xx_state* state) { u8 buf[2]; @@ -521,12 +681,32 @@ static int tda80xx_set_frontend(struct d { struct tda80xx_state* state = fe->demodulator_priv; + 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); + } + + tda80xx_set_parameters_compat(state, p->inversion, p->u.qpsk.symbol_rate, p->u.qpsk.fec_inner); + tda80xx_set_clk(state); + //tda80xx_set_scpc_freq_offset(state); + state->afc_loop = 1; + + return 0; +} + +static int tda80xx_set_params(struct dvb_frontend* fe, + struct dvbfe_params *p) +{ + struct tda80xx_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.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); } - tda80xx_set_parameters(state, p->inversion, p->u.qpsk.symbol_rate, p->u.qpsk.fec_inner); + tda80xx_set_parameters(state, p->inversion, p->delsys.dvbs.symbol_rate, p->delsys.dvbs.fec); tda80xx_set_clk(state); //tda80xx_set_scpc_freq_offset(state); state->afc_loop = 1; @@ -696,6 +876,37 @@ error: return NULL; } +static struct dvbfe_info dvbs_info = { + .name = "Philips TDA80xx 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 = 2700000, + .frequency_step = 125, + .symbol_rate_min = 4500000, + .symbol_rate_max = 45000000, +}; + +static int tda80xx_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info) +{ + memcpy(fe_info, &dvbs_info, sizeof (dvbs_info)); + + return 0; +} + +static int tda80xx_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_DVBS; + + return 0; +} + static struct dvb_frontend_ops tda80xx_ops = { .info = { @@ -733,6 +944,11 @@ static struct dvb_frontend_ops tda80xx_o .diseqc_send_burst = tda80xx_send_diseqc_burst, .set_tone = tda80xx_set_tone, .set_voltage = tda80xx_set_voltage, + + .set_params = tda80xx_set_params, + .get_params = tda80xx_get_params, + .get_info = tda80xx_get_info, + .get_delsys = tda80xx_get_delsys, }; module_param(debug, int, 0644); diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/ves1820.c mp-bc1/linux/drivers/media/dvb/frontends/ves1820.c --- v4l-dvb/linux/drivers/media/dvb/frontends/ves1820.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/ves1820.c 2006-07-17 23:46:22.000000000 +0400 @@ -219,9 +219,10 @@ static int ves1820_set_parameters(struct if (real_qam < 0 || real_qam > 4) 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); } ves1820_set_symbolrate(state, p->u.qam.symbol_rate); @@ -237,6 +238,62 @@ static int ves1820_set_parameters(struct return 0; } +static int ves1820_set_params(struct dvb_frontend* fe, + struct dvbfe_params *p) +{ + struct ves1820_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); + } + + ves1820_set_symbolrate(state, p->delsys.dvbc.symbol_rate); + ves1820_writereg(state, 0x34, state->pwm); + + switch (p->delsys.dvbc.modulation) { + case DVBFE_MOD_QAM16: + ves1820_writereg(state, 0x01, 140); + ves1820_writereg(state, 0x05, 135); + ves1820_writereg(state, 0x08, 162); + ves1820_writereg(state, 0x09, 145); + ves1820_setup_reg0(state, 0x00, p->inversion); + break; + case DVBFE_MOD_QAM32: + ves1820_writereg(state, 0x01, 140); + ves1820_writereg(state, 0x05, 100); + ves1820_writereg(state, 0x08, 116); + ves1820_writereg(state, 0x09, 150); + ves1820_setup_reg0(state, 0x04, p->inversion); + break; + case DVBFE_MOD_QAM64: + ves1820_writereg(state, 0x01, 106); + ves1820_writereg(state, 0x05, 70); + ves1820_writereg(state, 0x08, 67); + ves1820_writereg(state, 0x09, 106); + ves1820_setup_reg0(state, 0x08, p->inversion); + break; + case DVBFE_MOD_QAM128: + ves1820_writereg(state, 0x01, 100); + ves1820_writereg(state, 0x05, 54); + ves1820_writereg(state, 0x08, 52); + ves1820_writereg(state, 0x09, 126); + ves1820_setup_reg0(state, 0x0c, p->inversion); + case DVBFE_MOD_QAM256: + ves1820_writereg(state, 0x01, 92); + ves1820_writereg(state, 0x05, 38); + ves1820_writereg(state, 0x08, 35); + ves1820_writereg(state, 0x09, 107); + ves1820_setup_reg0(state, 0x10, p->inversion); + break; + default: + return -EINVAL; + } + ves1820_writereg(state, 2, ves1820_inittab[2] | (state->config->selagc ? 0x08 : 0)); + return 0; +} + static int ves1820_read_status(struct dvb_frontend* fe, fe_status_t* status) { struct ves1820_state* state = fe->demodulator_priv; @@ -341,6 +398,54 @@ static int ves1820_get_frontend(struct d return 0; } +static int ves1820_get_params(struct dvb_frontend* fe, + struct dvbfe_params *p) +{ + struct ves1820_state* state = fe->demodulator_priv; + int sync; + s8 afc = 0; + u32 modulation; + + sync = ves1820_readreg(state, 0x11); + afc = ves1820_readreg(state, 0x19); + if (verbose) { + /* AFC only valid when carrier has been recovered */ + printk(sync & 2 ? "ves1820: AFC (%d) %dHz\n" : + "ves1820: [AFC (%d) %dHz]\n", afc, -((s32) p->delsys.dvbc.symbol_rate * afc) >> 10); + } + + if (!state->config->invert) { + p->inversion = (state->reg0 & 0x20) ? INVERSION_ON : INVERSION_OFF; + } else { + p->inversion = (!(state->reg0 & 0x20)) ? INVERSION_ON : INVERSION_OFF; + } + + modulation = (state->reg0 >> 2) & 7; + switch (modulation) { + 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_QAM64; + break; + case 3: + p->delsys.dvbc.modulation = DVBFE_MOD_QAM128; + break; + case 4: + p->delsys.dvbc.modulation = DVBFE_MOD_QAM256; + break; + } + + p->frequency = ((p->frequency + 31250) / 62500) * 62500; + if (sync & 2) + p->frequency -= ((s32) p->delsys.dvbc.symbol_rate * afc) >> 10; + + return 0; +} + static int ves1820_sleep(struct dvb_frontend* fe) { struct ves1820_state* state = fe->demodulator_priv; @@ -405,6 +510,32 @@ error: return NULL; } +static struct dvbfe_info dvbc_info = { + .name = "VLSI VES1820 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_step = 62500, +}; + +static int ves1820_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info) +{ + memcpy(fe_info, &dvbc_info, sizeof (dvbc_info)); + + return 0; +} + +static int ves1820_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_DVBC; + + return 0; +} + static struct dvb_frontend_ops ves1820_ops = { .info = { @@ -435,6 +566,11 @@ static struct dvb_frontend_ops ves1820_o .read_signal_strength = ves1820_read_signal_strength, .read_snr = ves1820_read_snr, .read_ucblocks = ves1820_read_ucblocks, + + .set_params = ves1820_set_params, + .get_params = ves1820_get_params, + .get_info = ves1820_get_info, + .get_delsys = ves1820_get_delsys, }; module_param(verbose, int, 0644); diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/ves1x93.c mp-bc1/linux/drivers/media/dvb/frontends/ves1x93.c --- v4l-dvb/linux/drivers/media/dvb/frontends/ves1x93.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/ves1x93.c 2006-07-17 23:46:28.000000000 +0400 @@ -155,7 +155,7 @@ static int ves1x93_set_inversion (struct return ves1x93_writereg (state, 0x0c, (state->init_1x93_tab[0x0c] & 0x3f) | val); } -static int ves1x93_set_fec (struct ves1x93_state* state, fe_code_rate_t fec) +static int ves1x93_set_fec_compat(struct ves1x93_state* state, fe_code_rate_t fec) { if (fec == FEC_AUTO) return ves1x93_writereg (state, 0x0d, 0x08); @@ -165,11 +165,74 @@ static int ves1x93_set_fec (struct ves1x return ves1x93_writereg (state, 0x0d, fec - FEC_1_2); } -static fe_code_rate_t ves1x93_get_fec (struct ves1x93_state* state) +static int ves1x93_set_fec(struct ves1x93_state* state, enum dvbfe_fec fec) +{ + + switch (fec) { + case DVBFE_FEC_1_2: + return ves1x93_writereg(state, 0x0d, 0x00); + case DVBFE_FEC_2_3: + return ves1x93_writereg(state, 0x0d, 0x01); + case DVBFE_FEC_3_4: + return ves1x93_writereg(state, 0x0d, 0x02); + case DVBFE_FEC_4_5: + return ves1x93_writereg(state, 0x0d, 0x03); + case DVBFE_FEC_5_6: + return ves1x93_writereg(state, 0x0d, 0x04); + case DVBFE_FEC_6_7: + return ves1x93_writereg(state, 0x0d, 0x05); + case DVBFE_FEC_7_8: + return ves1x93_writereg(state, 0x0d, 0x06); + case DVBFE_FEC_8_9: + return ves1x93_writereg(state, 0x0d, 0x07); + case DVBFE_FEC_AUTO: + return ves1x93_writereg(state, 0x0d, 0x08); + default: + return -EINVAL; + } +} + +static fe_code_rate_t ves1x93_get_fec_compat(struct ves1x93_state* state) { return FEC_1_2 + ((ves1x93_readreg (state, 0x0d) >> 4) & 0x7); } +static enum dvbfe_fec ves1x93_get_fec(struct ves1x93_state* state, + struct dvbfe_params *p) +{ + u32 fec; + + fec = (ves1x93_readreg(state, 0x0d) >> 4) & 0x07; + switch (fec) { + case 0: + p->delsys.dvbs.fec = DVBFE_FEC_1_2; + break; + case 1: + p->delsys.dvbs.fec = DVBFE_FEC_2_3; + break; + case 2: + p->delsys.dvbs.fec = DVBFE_FEC_3_4; + break; + case 3: + p->delsys.dvbs.fec = DVBFE_FEC_4_5; + break; + case 4: + p->delsys.dvbs.fec = DVBFE_FEC_5_6; + break; + case 5: + p->delsys.dvbs.fec = DVBFE_FEC_6_7; + break; + case 6: + p->delsys.dvbs.fec = DVBFE_FEC_7_8; + break; + case 7: + p->delsys.dvbs.fec = DVBFE_FEC_8_9; + break; + } + + return 0; +} + static int ves1x93_set_symbolrate (struct ves1x93_state* state, u32 srate) { u32 BDR; @@ -388,13 +451,32 @@ static int ves1x93_set_frontend(struct d { struct ves1x93_state* state = fe->demodulator_priv; + 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); + } + ves1x93_set_inversion(state, p->inversion); + ves1x93_set_fec_compat(state, p->u.qpsk.fec_inner); + ves1x93_set_symbolrate(state, p->u.qpsk.symbol_rate); + state->inversion = p->inversion; + + return 0; +} + +static int ves1x93_set_params(struct dvb_frontend* fe, + struct dvbfe_params *p) +{ + struct ves1x93_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.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); } - ves1x93_set_inversion (state, p->inversion); - ves1x93_set_fec (state, p->u.qpsk.fec_inner); - ves1x93_set_symbolrate (state, p->u.qpsk.symbol_rate); + ves1x93_set_inversion(state, p->inversion); + ves1x93_set_fec(state, p->delsys.dvbs.fec); + ves1x93_set_symbolrate (state, p->delsys.dvbs.symbol_rate); state->inversion = p->inversion; return 0; @@ -417,7 +499,31 @@ static int ves1x93_get_frontend(struct d if (state->inversion == INVERSION_AUTO) p->inversion = (ves1x93_readreg (state, 0x0f) & 2) ? INVERSION_OFF : INVERSION_ON; - p->u.qpsk.fec_inner = ves1x93_get_fec (state); + p->u.qpsk.fec_inner = ves1x93_get_fec_compat(state); + /* XXX FIXME: timing offset !! */ + + return 0; +} + +static int ves1x93_get_params(struct dvb_frontend* fe, + struct dvbfe_params *p) +{ + struct ves1x93_state* state = fe->demodulator_priv; + int afc; + + afc = ((int)((char)(ves1x93_readreg (state, 0x0a) << 1))) / 2; + afc = (afc * (int)(p->delsys.dvbs.symbol_rate / 1000 / 8)) / 16; + + p->frequency -= afc; + + /* + * inversion indicator is only valid + * if auto inversion was used + */ + if (state->inversion == INVERSION_AUTO) + p->inversion = (ves1x93_readreg (state, 0x0f) & 2) ? + INVERSION_OFF : INVERSION_ON; + p->delsys.dvbs.fec = ves1x93_get_fec(state, p); /* XXX FIXME: timing offset !! */ return 0; @@ -505,6 +611,37 @@ error: return NULL; } +static struct dvbfe_info dvbs_info = { + .name = "VLSI VES1x93 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 = 125, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, +}; + +static int ves1x93_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info) +{ + memcpy(fe_info, &dvbs_info, sizeof (dvbs_info)); + + return 0; +} + +static int ves1x93_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_DVBS; + + return 0; +} + static struct dvb_frontend_ops ves1x93_ops = { .info = { @@ -539,6 +676,11 @@ static struct dvb_frontend_ops ves1x93_o .read_ucblocks = ves1x93_read_ucblocks, .set_voltage = ves1x93_set_voltage, + + .set_params = ves1x93_set_params, + .get_params = ves1x93_get_params, + .get_info = ves1x93_get_info, + .get_delsys = ves1x93_get_delsys, }; module_param(debug, int, 0644); diff -Naurp v4l-dvb/linux/drivers/media/dvb/frontends/zl10353.c mp-bc1/linux/drivers/media/dvb/frontends/zl10353.c --- v4l-dvb/linux/drivers/media/dvb/frontends/zl10353.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/zl10353.c 2006-07-17 23:46:33.000000000 +0400 @@ -149,15 +149,75 @@ static int zl10353_set_parameters(struct // if there is no attached secondary tuner, we call set_params to program // a potential tuner attached somewhere else if (state->config.no_tuner) { + if (fe->ops.tuner_ops.set_params_compat) { + fe->ops.tuner_ops.set_params_compat(fe, param); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + } + } + + // if pllbuf is defined, retrieve the settings + if (fe->ops.tuner_ops.calc_regs_compat) { + fe->ops.tuner_ops.calc_regs_compat(fe, param, pllbuf+1, 5); + pllbuf[1] <<= 1; + } else { + // fake pllbuf settings + pllbuf[1] = 0x61 << 1; + pllbuf[2] = 0; + pllbuf[3] = 0; + pllbuf[3] = 0; + pllbuf[4] = 0; + } + + // there is no call to _just_ start decoding, so we send the pllbuf anyway + // even if there isn't a PLL attached to the secondary bus + zl10353_write(fe, pllbuf, sizeof (pllbuf)); + + zl10353_single_write(fe, 0x70, 0x01); + udelay(250); + zl10353_single_write(fe, 0xE4, 0x00); + zl10353_single_write(fe, 0xE5, 0x2A); + zl10353_single_write(fe, 0xE9, 0x02); + zl10353_single_write(fe, 0xE7, 0x40); + zl10353_single_write(fe, 0xE8, 0x10); + + return 0; +} + +static int zl10353_set_params(struct dvb_frontend *fe, + struct dvbfe_params *param) +{ + struct zl10353_state *state = fe->demodulator_priv; + + u8 pllbuf[6] = { 0x67 }; + + /* These settings set "auto-everything" and start the FSM. */ + zl10353_single_write(fe, 0x55, 0x80); + udelay(200); + zl10353_single_write(fe, 0xEA, 0x01); + udelay(200); + zl10353_single_write(fe, 0xEA, 0x00); + + zl10353_single_write(fe, 0x56, 0x28); + zl10353_single_write(fe, 0x89, 0x20); + zl10353_single_write(fe, 0x5E, 0x00); + zl10353_single_write(fe, 0x65, 0x5A); + zl10353_single_write(fe, 0x66, 0xE9); + zl10353_single_write(fe, 0x62, 0x0A); + + // if there is no attached secondary tuner, we call set_params to program + // a potential tuner attached somewhere else + if (state->config.no_tuner) { if (fe->ops.tuner_ops.set_params) { fe->ops.tuner_ops.set_params(fe, param); - if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); } } // if pllbuf is defined, retrieve the settings if (fe->ops.tuner_ops.calc_regs) { - fe->ops.tuner_ops.calc_regs(fe, param, pllbuf+1, 5); + fe->ops.tuner_ops.calc_regs(fe, param, pllbuf + 1, 5); pllbuf[1] <<= 1; } else { // fake pllbuf settings @@ -170,7 +230,7 @@ static int zl10353_set_parameters(struct // there is no call to _just_ start decoding, so we send the pllbuf anyway // even if there isn't a PLL attached to the secondary bus - zl10353_write(fe, pllbuf, sizeof(pllbuf)); + zl10353_write(fe, pllbuf, sizeof (pllbuf)); zl10353_single_write(fe, 0x70, 0x01); udelay(250); @@ -302,6 +362,35 @@ error: return NULL; } +static struct dvbfe_info dvbt_info = { + .name = "Zarlink ZL10353 DVB-T", + .delivery = DVBFE_DELSYS_DVBT, + .delsys = { + .dvbt.modulation = DVBFE_MOD_OFDM, + .dvbt.stream_priority = DVBFE_STREAM_PRIORITY_HP | + DVBFE_STREAM_PRIORITY_LP, + }, + + .frequency_min = 174000000, + .frequency_max = 862000000, + .frequency_step = 166667, + .frequency_tolerance = 0, +}; + +static int zl10353_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info) +{ + memcpy(fe_info, &dvbt_info, sizeof (dvbt_info)); + + return 0; +} + +static int zl10353_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_DVBT; + + return 0; +} + static struct dvb_frontend_ops zl10353_ops = { .info = { @@ -330,6 +419,10 @@ static struct dvb_frontend_ops zl10353_o .read_status = zl10353_read_status, .read_snr = zl10353_read_snr, + + .set_params = zl10353_set_params, + .get_info = zl10353_get_info, + .get_delsys = zl10353_get_delsys, }; #if 1