summaryrefslogtreecommitdiff
path: root/linux/drivers/media/dvb
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2007-12-20 07:37:17 -0200
committerMauro Carvalho Chehab <mchehab@infradead.org>2007-12-20 07:37:17 -0200
commit75cd5f355fe382a2645a959e6ff2beffa09019da (patch)
treed78404ed6886ea5ab11db15af0ec3deb1bbd9952 /linux/drivers/media/dvb
parentd70b230414d9b4799b0091981a1d4f9cd55d9a84 (diff)
parent3842afc175a16c86d1f3b719f07a3bfddf3c7815 (diff)
downloadmediapointer-dvb-s2-75cd5f355fe382a2645a959e6ff2beffa09019da.tar.gz
mediapointer-dvb-s2-75cd5f355fe382a2645a959e6ff2beffa09019da.tar.bz2
merge: http://www.linuxtv.org/hg/~hverkuil/v4l-dvb
From: Mauro Carvalho Chehab <mchehab@infradead.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'linux/drivers/media/dvb')
-rw-r--r--linux/drivers/media/dvb/frontends/s5h1409.c45
-rw-r--r--linux/drivers/media/dvb/frontends/s5h1409.h4
-rw-r--r--linux/drivers/media/dvb/frontends/tda18271.h2
-rw-r--r--linux/drivers/media/dvb/frontends/zl10353.c246
-rw-r--r--linux/drivers/media/dvb/frontends/zl10353_priv.h15
5 files changed, 280 insertions, 32 deletions
diff --git a/linux/drivers/media/dvb/frontends/s5h1409.c b/linux/drivers/media/dvb/frontends/s5h1409.c
index 188bcb247..29ec9ac8f 100644
--- a/linux/drivers/media/dvb/frontends/s5h1409.c
+++ b/linux/drivers/media/dvb/frontends/s5h1409.c
@@ -42,6 +42,7 @@ struct s5h1409_state {
fe_modulation_t current_modulation;
u32 current_frequency;
+ int if_freq;
u32 is_qam_locked;
u32 qam_state;
@@ -107,7 +108,7 @@ static struct vsb_snr_tab {
u16 val;
u16 data;
} vsb_snr_tab[] = {
- { 1023, 770, },
+ { 924, 300, },
{ 923, 300, },
{ 918, 295, },
{ 915, 290, },
@@ -154,6 +155,7 @@ static struct qam64_snr_tab {
u16 val;
u16 data;
} qam64_snr_tab[] = {
+ { 1, 0, },
{ 12, 300, },
{ 15, 290, },
{ 18, 280, },
@@ -217,6 +219,7 @@ static struct qam64_snr_tab {
{ 95, 202, },
{ 96, 201, },
{ 104, 200, },
+ { 255, 0, },
};
/* QAM256 SNR lookup table */
@@ -224,6 +227,7 @@ static struct qam256_snr_tab {
u16 val;
u16 data;
} qam256_snr_tab[] = {
+ { 1, 0, },
{ 12, 400, },
{ 13, 390, },
{ 15, 380, },
@@ -292,6 +296,7 @@ static struct qam256_snr_tab {
{ 105, 262, },
{ 106, 261, },
{ 110, 260, },
+ { 255, 0, },
};
/* 8 bit registers, 16 bit values */
@@ -344,28 +349,32 @@ static int s5h1409_softreset(struct dvb_frontend* fe)
return 0;
}
+#define S5H1409_VSB_IF_FREQ 5380
+#define S5H1409_QAM_IF_FREQ state->config->qam_if
+
static int s5h1409_set_if_freq(struct dvb_frontend* fe, int KHz)
{
struct s5h1409_state* state = fe->demodulator_priv;
- int ret = 0;
dprintk("%s(%d KHz)\n", __FUNCTION__, KHz);
- if( (KHz == 44000) || (KHz == 5380) ) {
- s5h1409_writereg(state, 0x87, 0x01be);
- s5h1409_writereg(state, 0x88, 0x0436);
- s5h1409_writereg(state, 0x89, 0x054d);
- } else
- if (KHz == 4000) {
+ switch (KHz) {
+ case 4000:
s5h1409_writereg(state, 0x87, 0x014b);
s5h1409_writereg(state, 0x88, 0x0cb5);
s5h1409_writereg(state, 0x89, 0x03e2);
- } else {
- printk("%s() Invalid arg = %d KHz\n", __FUNCTION__, KHz);
- ret = -1;
+ break;
+ case 5380:
+ case 44000:
+ default:
+ s5h1409_writereg(state, 0x87, 0x01be);
+ s5h1409_writereg(state, 0x88, 0x0436);
+ s5h1409_writereg(state, 0x89, 0x054d);
+ break;
}
+ state->if_freq = KHz;
- return ret;
+ return 0;
}
static int s5h1409_set_spectralinversion(struct dvb_frontend* fe, int inverted)
@@ -390,11 +399,15 @@ static int s5h1409_enable_modulation(struct dvb_frontend* fe,
switch(m) {
case VSB_8:
dprintk("%s() VSB_8\n", __FUNCTION__);
+ if (state->if_freq != S5H1409_VSB_IF_FREQ)
+ s5h1409_set_if_freq(fe, S5H1409_VSB_IF_FREQ);
s5h1409_writereg(state, 0xf4, 0);
break;
case QAM_64:
case QAM_256:
dprintk("%s() QAM_AUTO (64/256)\n", __FUNCTION__);
+ if (state->if_freq != S5H1409_QAM_IF_FREQ)
+ s5h1409_set_if_freq(fe, S5H1409_QAM_IF_FREQ);
s5h1409_writereg(state, 0xf4, 1);
s5h1409_writereg(state, 0x85, 0x110);
break;
@@ -567,7 +580,7 @@ static int s5h1409_init (struct dvb_frontend* fe)
s5h1409_writereg(state, 0xab, 0x0); /* Parallel */
s5h1409_set_spectralinversion(fe, state->config->inversion);
- s5h1409_set_if_freq(fe, state->config->if_freq);
+ s5h1409_set_if_freq(fe, state->if_freq);
s5h1409_set_gpio(fe, state->config->gpio);
s5h1409_softreset(fe);
@@ -670,14 +683,15 @@ static int s5h1409_read_snr(struct dvb_frontend* fe, u16* snr)
u16 reg;
dprintk("%s()\n", __FUNCTION__);
- reg = s5h1409_readreg(state, 0xf1) & 0x1ff;
-
switch(state->current_modulation) {
case QAM_64:
+ reg = s5h1409_readreg(state, 0xf0) & 0xff;
return s5h1409_qam64_lookup_snr(fe, snr, reg);
case QAM_256:
+ reg = s5h1409_readreg(state, 0xf0) & 0xff;
return s5h1409_qam256_lookup_snr(fe, snr, reg);
case VSB_8:
+ reg = s5h1409_readreg(state, 0xf1) & 0x3ff;
return s5h1409_vsb_lookup_snr(fe, snr, reg);
default:
break;
@@ -746,6 +760,7 @@ struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
state->config = config;
state->i2c = i2c;
state->current_modulation = 0;
+ state->if_freq = S5H1409_VSB_IF_FREQ;
/* check if the demod exists */
if (s5h1409_readreg(state, 0x04) != 0x0066)
diff --git a/linux/drivers/media/dvb/frontends/s5h1409.h b/linux/drivers/media/dvb/frontends/s5h1409.h
index 20f9af1af..b1f433906 100644
--- a/linux/drivers/media/dvb/frontends/s5h1409.h
+++ b/linux/drivers/media/dvb/frontends/s5h1409.h
@@ -39,8 +39,8 @@ struct s5h1409_config
#define S5H1409_GPIO_ON 1
u8 gpio;
- /* IF Freq in KHz */
- u16 if_freq;
+ /* IF Freq for QAM in KHz, VSB is hardcoded to 5380 */
+ u16 qam_if;
/* Spectral Inversion */
#define S5H1409_INVERSION_OFF 0
diff --git a/linux/drivers/media/dvb/frontends/tda18271.h b/linux/drivers/media/dvb/frontends/tda18271.h
index d84003372..b98a9331c 100644
--- a/linux/drivers/media/dvb/frontends/tda18271.h
+++ b/linux/drivers/media/dvb/frontends/tda18271.h
@@ -38,7 +38,7 @@ extern struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
static inline struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe,
u8 addr,
struct i2c_adapter *i2c,
- enum tda18271_i2c_gate gate);
+ enum tda18271_i2c_gate gate)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
return NULL;
diff --git a/linux/drivers/media/dvb/frontends/zl10353.c b/linux/drivers/media/dvb/frontends/zl10353.c
index 276612e00..79802e023 100644
--- a/linux/drivers/media/dvb/frontends/zl10353.c
+++ b/linux/drivers/media/dvb/frontends/zl10353.c
@@ -37,6 +37,8 @@ struct zl10353_state {
struct dvb_frontend frontend;
struct zl10353_config config;
+
+ enum fe_bandwidth bandwidth;
};
static int debug;
@@ -149,7 +151,8 @@ static void zl10353_calc_nominal_rate(struct dvb_frontend *fe,
break;
}
- value = (bw * (u64)10 * (1 << 23) / 7 * 125 + adc_clock / 2);
+ value = (u64)10 * (1 << 23) / 7 * 125;
+ value = (bw * value) + adc_clock / 2;
do_div(value, adc_clock);
*nominal_rate = value;
@@ -199,27 +202,156 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
{
struct zl10353_state *state = fe->demodulator_priv;
u16 nominal_rate, input_freq;
- u8 pllbuf[6] = { 0x67 };
+ u8 pllbuf[6] = { 0x67 }, acq_ctl = 0;
+ u16 tps = 0;
+ struct dvb_ofdm_parameters *op = &param->u.ofdm;
- /* These settings set "auto-everything" and start the FSM. */
- zl10353_single_write(fe, 0x55, 0x80);
+ zl10353_single_write(fe, RESET, 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, AGC_TARGET, 0x28);
+
+ if (op->transmission_mode != TRANSMISSION_MODE_AUTO)
+ acq_ctl |= (1 << 0);
+ if (op->guard_interval != GUARD_INTERVAL_AUTO)
+ acq_ctl |= (1 << 1);
+ zl10353_single_write(fe, ACQ_CTL, acq_ctl);
- zl10353_calc_nominal_rate(fe, param->u.ofdm.bandwidth, &nominal_rate);
+ switch (op->bandwidth) {
+ case BANDWIDTH_6_MHZ:
+ /* These are extrapolated from the 7 and 8MHz values */
+ zl10353_single_write(fe, MCLK_RATIO, 0x97);
+ zl10353_single_write(fe, 0x64, 0x34);
+ break;
+ case BANDWIDTH_7_MHZ:
+ zl10353_single_write(fe, MCLK_RATIO, 0x86);
+ zl10353_single_write(fe, 0x64, 0x35);
+ break;
+ case BANDWIDTH_8_MHZ:
+ default:
+ zl10353_single_write(fe, MCLK_RATIO, 0x75);
+ zl10353_single_write(fe, 0x64, 0x36);
+ }
+
+ zl10353_calc_nominal_rate(fe, op->bandwidth, &nominal_rate);
zl10353_single_write(fe, TRL_NOMINAL_RATE_1, msb(nominal_rate));
zl10353_single_write(fe, TRL_NOMINAL_RATE_0, lsb(nominal_rate));
+ state->bandwidth = op->bandwidth;
zl10353_calc_input_freq(fe, &input_freq);
zl10353_single_write(fe, INPUT_FREQ_1, msb(input_freq));
zl10353_single_write(fe, INPUT_FREQ_0, lsb(input_freq));
+ /* Hint at TPS settings */
+ switch (op->code_rate_HP) {
+ case FEC_2_3:
+ tps |= (1 << 7);
+ break;
+ case FEC_3_4:
+ tps |= (2 << 7);
+ break;
+ case FEC_5_6:
+ tps |= (3 << 7);
+ break;
+ case FEC_7_8:
+ tps |= (4 << 7);
+ break;
+ case FEC_1_2:
+ case FEC_AUTO:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (op->code_rate_LP) {
+ case FEC_2_3:
+ tps |= (1 << 4);
+ break;
+ case FEC_3_4:
+ tps |= (2 << 4);
+ break;
+ case FEC_5_6:
+ tps |= (3 << 4);
+ break;
+ case FEC_7_8:
+ tps |= (4 << 4);
+ break;
+ case FEC_1_2:
+ case FEC_AUTO:
+ break;
+ case FEC_NONE:
+ if (op->hierarchy_information == HIERARCHY_AUTO ||
+ op->hierarchy_information == HIERARCHY_NONE)
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (op->constellation) {
+ case QPSK:
+ break;
+ case QAM_AUTO:
+ case QAM_16:
+ tps |= (1 << 13);
+ break;
+ case QAM_64:
+ tps |= (2 << 13);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (op->transmission_mode) {
+ case TRANSMISSION_MODE_2K:
+ case TRANSMISSION_MODE_AUTO:
+ break;
+ case TRANSMISSION_MODE_8K:
+ tps |= (1 << 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (op->guard_interval) {
+ case GUARD_INTERVAL_1_32:
+ case GUARD_INTERVAL_AUTO:
+ break;
+ case GUARD_INTERVAL_1_16:
+ tps |= (1 << 2);
+ break;
+ case GUARD_INTERVAL_1_8:
+ tps |= (2 << 2);
+ break;
+ case GUARD_INTERVAL_1_4:
+ tps |= (3 << 2);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (op->hierarchy_information) {
+ case HIERARCHY_AUTO:
+ case HIERARCHY_NONE:
+ break;
+ case HIERARCHY_1:
+ tps |= (1 << 10);
+ break;
+ case HIERARCHY_2:
+ tps |= (2 << 10);
+ break;
+ case HIERARCHY_4:
+ tps |= (3 << 10);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ zl10353_single_write(fe, TPS_GIVEN_1, msb(tps));
+ zl10353_single_write(fe, TPS_GIVEN_0, lsb(tps));
+
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
@@ -248,12 +380,97 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
else
zl10353_single_write(fe, TUNER_GO, 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_get_parameters(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *param)
+{
+ struct zl10353_state *state = fe->demodulator_priv;
+ struct dvb_ofdm_parameters *op = &param->u.ofdm;
+ int s6, s9;
+ u16 tps;
+ static const u8 tps_fec_to_api[8] = {
+ FEC_1_2,
+ FEC_2_3,
+ FEC_3_4,
+ FEC_5_6,
+ FEC_7_8,
+ FEC_AUTO,
+ FEC_AUTO,
+ FEC_AUTO
+ };
+
+ s6 = zl10353_read_register(state, STATUS_6);
+ s9 = zl10353_read_register(state, STATUS_9);
+ if (s6 < 0 || s9 < 0)
+ return -EREMOTEIO;
+ if ((s6 & (1 << 5)) == 0 || (s9 & (1 << 4)) == 0)
+ return -EINVAL; /* no FE or TPS lock */
+
+ tps = zl10353_read_register(state, TPS_RECEIVED_1) << 8 |
+ zl10353_read_register(state, TPS_RECEIVED_0);
+
+ 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 = QPSK;
+ break;
+ case 1:
+ op->constellation = QAM_16;
+ break;
+ case 2:
+ op->constellation = QAM_64;
+ break;
+ default:
+ op->constellation = QAM_AUTO;
+ break;
+ }
+
+ op->transmission_mode = (tps & 0x01) ? TRANSMISSION_MODE_8K :
+ TRANSMISSION_MODE_2K;
+
+ switch ((tps >> 2) & 3) {
+ case 0:
+ op->guard_interval = GUARD_INTERVAL_1_32;
+ break;
+ case 1:
+ op->guard_interval = GUARD_INTERVAL_1_16;
+ break;
+ case 2:
+ op->guard_interval = GUARD_INTERVAL_1_8;
+ break;
+ case 3:
+ op->guard_interval = GUARD_INTERVAL_1_4;
+ break;
+ default:
+ op->guard_interval = GUARD_INTERVAL_AUTO;
+ break;
+ }
+
+ switch ((tps >> 10) & 7) {
+ case 0:
+ op->hierarchy_information = HIERARCHY_NONE;
+ break;
+ case 1:
+ op->hierarchy_information = HIERARCHY_1;
+ break;
+ case 2:
+ op->hierarchy_information = HIERARCHY_2;
+ break;
+ case 3:
+ op->hierarchy_information = HIERARCHY_4;
+ break;
+ default:
+ op->hierarchy_information = HIERARCHY_AUTO;
+ break;
+ }
+
+ param->frequency = 0;
+ op->bandwidth = state->bandwidth;
+ param->inversion = INVERSION_AUTO;
return 0;
}
@@ -448,6 +665,7 @@ static struct dvb_frontend_ops zl10353_ops = {
.write = zl10353_write,
.set_frontend = zl10353_set_parameters,
+ .get_frontend = zl10353_get_parameters,
.get_tune_settings = zl10353_get_tune_settings,
.read_status = zl10353_read_status,
diff --git a/linux/drivers/media/dvb/frontends/zl10353_priv.h b/linux/drivers/media/dvb/frontends/zl10353_priv.h
index fcad92219..055ff1f7e 100644
--- a/linux/drivers/media/dvb/frontends/zl10353_priv.h
+++ b/linux/drivers/media/dvb/frontends/zl10353_priv.h
@@ -46,13 +46,28 @@ enum zl10353_reg_addr {
RS_ERR_CNT_0 = 0x13,
RS_UBC_1 = 0x14,
RS_UBC_0 = 0x15,
+ TPS_RECEIVED_1 = 0x1D,
+ TPS_RECEIVED_0 = 0x1E,
+ TPS_CURRENT_1 = 0x1F,
+ TPS_CURRENT_0 = 0x20,
+ RESET = 0x55,
+ AGC_TARGET = 0x56,
+ MCLK_RATIO = 0x5C,
+ ACQ_CTL = 0x5E,
TRL_NOMINAL_RATE_1 = 0x65,
TRL_NOMINAL_RATE_0 = 0x66,
INPUT_FREQ_1 = 0x6C,
INPUT_FREQ_0 = 0x6D,
+ TPS_GIVEN_1 = 0x6E,
+ TPS_GIVEN_0 = 0x6F,
TUNER_GO = 0x70,
FSM_GO = 0x71,
CHIP_ID = 0x7F,
+ CHAN_STEP_1 = 0xE4,
+ CHAN_STEP_0 = 0xE5,
+ OFDM_LOCK_TIME = 0xE7,
+ FEC_LOCK_TIME = 0xE8,
+ ACQ_DELAY = 0xE9,
};
#endif /* _ZL10353_PRIV_ */