summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux/drivers/media/dvb/frontends/mt312.c91
1 files changed, 74 insertions, 17 deletions
diff --git a/linux/drivers/media/dvb/frontends/mt312.c b/linux/drivers/media/dvb/frontends/mt312.c
index b94adc4e3..58fb627ec 100644
--- a/linux/drivers/media/dvb/frontends/mt312.c
+++ b/linux/drivers/media/dvb/frontends/mt312.c
@@ -39,11 +39,19 @@
#define MT312_DEBUG 0
#define MT312_SYS_CLK 90000000UL /* 90 MHz */
+#define MT312_LPOWER_SYS_CLK 60000000UL /* 60 MHz */
#define MT312_PLL_CLK 10000000UL /* 10 MHz */
/* number of active frontends */
static int mt312_count = 0;
+#if MT312_DEBUG == 0
+#define dprintk(x...)
+#else
+static int debug = 0;
+#define dprintk if(debug == 1) printk
+#endif
+
static struct dvb_frontend_info mt312_info = {
.name = "Zarlink MT312",
.type = FE_QPSK,
@@ -86,7 +94,7 @@ static int mt312_read(struct dvb_i2c_bus *i2c,
return -EREMOTEIO;
}
#if MT312_DEBUG
- {
+ if(debug) {
int i;
printk(KERN_INFO "R(%d):", reg & 0x7f);
for (i = 0; i < count; i++)
@@ -107,7 +115,7 @@ static int mt312_write(struct dvb_i2c_bus *i2c,
struct i2c_msg msg;
#if MT312_DEBUG
- {
+ if(debug) {
int i;
printk(KERN_INFO "W(%d):", reg & 0x7f);
for (i = 0; i < count; i++)
@@ -205,7 +213,7 @@ static int sl1935_set_tv_freq(struct dvb_i2c_bus *i2c, u32 freq, u32 sr)
if (freq < 1550000)
buf[3] |= 0x10;
- printk(KERN_INFO "synth dword = %02x%02x%02x%02x\n", buf[0],
+ dprintk(KERN_INFO "synth dword = %02x%02x%02x%02x\n", buf[0],
buf[1], buf[2], buf[3]);
return mt312_pll_write(i2c, I2C_ADDR_SL1935, buf, sizeof(buf));
@@ -225,7 +233,7 @@ static int tsa5059_set_tv_freq(struct dvb_i2c_bus *i2c, u32 freq, u32 sr)
if (freq < 1550000)
buf[3] |= 0x02;
- printk(KERN_INFO "synth dword = %02x%02x%02x%02x\n", buf[0],
+ dprintk(KERN_INFO "synth dword = %02x%02x%02x%02x\n", buf[0],
buf[1], buf[2], buf[3]);
return mt312_pll_write(i2c, I2C_ADDR_TSA5059, buf, sizeof(buf));
@@ -236,13 +244,13 @@ static int mt312_reset(struct dvb_i2c_bus *i2c, const u8 full)
return mt312_writereg(i2c, RESET, full ? 0x80 : 0x40);
}
-static int mt312_init(struct dvb_i2c_bus *i2c, const long id)
+static int mt312_init(struct dvb_i2c_bus *i2c, const long id, u8 pll)
{
int ret;
u8 buf[2];
/* wake up */
- if ((ret = mt312_writereg(i2c, CONFIG, 0x8c)) < 0)
+ if ((ret = mt312_writereg(i2c, CONFIG, (pll == 60 ? 0x88 : 0x8c))) < 0)
return ret;
/* wait at least 150 usec */
@@ -252,8 +260,17 @@ static int mt312_init(struct dvb_i2c_bus *i2c, const long id)
if ((ret = mt312_reset(i2c, 1)) < 0)
return ret;
+// Per datasheet, write correct values. 09/28/03 ACCJr.
+// If we don't do this, we won't get FE_HAS_VITERBI in the VP310.
+ {
+ u8 buf_def[8]={0x14, 0x12, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00};
+
+ if ((ret = mt312_write(i2c, VIT_SETUP, buf_def, sizeof(buf_def))) < 0)
+ return ret;
+ }
+
/* SYS_CLK */
- buf[0] = mt312_div(MT312_SYS_CLK * 2, 1000000);
+ buf[0] = mt312_div((pll == 60 ? MT312_LPOWER_SYS_CLK : MT312_SYS_CLK) * 2, 1000000);
/* DISEQC_RATIO */
buf[1] = mt312_div(MT312_PLL_CLK, 15000 * 4);
@@ -370,16 +387,18 @@ static int mt312_set_voltage(struct dvb_i2c_bus *i2c, const fe_sec_voltage_t v)
return mt312_writereg(i2c, DISEQC_MODE, volt_tab[v]);
}
-static int mt312_read_status(struct dvb_i2c_bus *i2c, fe_status_t *s)
+static int mt312_read_status(struct dvb_i2c_bus *i2c, fe_status_t *s, const long id)
{
int ret;
- u8 status[3];
+ u8 status[3], vit_mode;
*s = 0;
if ((ret = mt312_read(i2c, QPSK_STAT_H, status, sizeof(status))) < 0)
return ret;
+ dprintk(KERN_DEBUG "QPSK_STAT_H: 0x%02x, QPSK_STAT_L: 0x%02x, FEC_STATUS: 0x%02x\n", status[0], status[1], status[2]);
+
if (status[0] & 0xc0)
*s |= FE_HAS_SIGNAL; /* signal noise ratio */
if (status[0] & 0x04)
@@ -390,6 +409,16 @@ static int mt312_read_status(struct dvb_i2c_bus *i2c, fe_status_t *s)
*s |= FE_HAS_SYNC; /* byte align lock */
if (status[0] & 0x01)
*s |= FE_HAS_LOCK; /* qpsk lock */
+ // VP310 doesn't have AUTO, so we "implement it here" ACCJr
+ if ((id == ID_VP310) && !(status[0] & 0x01)) {
+ if ((ret = mt312_readreg(i2c, VIT_MODE, &vit_mode)) < 0)
+ return ret;
+ vit_mode ^= 0x40;
+ if ((ret = mt312_writereg(i2c, VIT_MODE, vit_mode)) < 0)
+ return ret;
+ if ((ret = mt312_writereg(i2c, GO, 0x01)) < 0)
+ return ret;
+ }
return 0;
}
@@ -422,7 +451,7 @@ static int mt312_read_agc(struct dvb_i2c_bus *i2c, u16 *signal_strength)
*signal_strength = agc;
- printk(KERN_DEBUG "agc=%08x err_db=%hd\n", agc, err_db);
+ dprintk(KERN_DEBUG "agc=%08x err_db=%hd\n", agc, err_db);
return 0;
}
@@ -458,7 +487,7 @@ static int mt312_set_frontend(struct dvb_i2c_bus *i2c,
const long id)
{
int ret;
- u8 buf[5];
+ u8 buf[5], config_val;
u16 sr;
const u8 fec_tab[10] =
@@ -467,6 +496,8 @@ static int mt312_set_frontend(struct dvb_i2c_bus *i2c,
int (*set_tv_freq)(struct dvb_i2c_bus *i2c, u32 freq, u32 sr);
+ dprintk("%s: Freq %d\n", __FUNCTION__, p->frequency);
+
if ((p->frequency < mt312_info.frequency_min)
|| (p->frequency > mt312_info.frequency_max))
return -EINVAL;
@@ -489,6 +520,22 @@ static int mt312_set_frontend(struct dvb_i2c_bus *i2c,
switch (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
+ if ((ret = mt312_readreg(i2c, CONFIG, &config_val) < 0))
+ return ret;
+ if (p->u.qpsk.symbol_rate >= 30000000) //Note that 30MS/s should use 90MHz
+ {
+ if ((config_val & 0x0c) == 0x08) //We are running 60MHz
+ if ((ret = mt312_init(i2c, id, (u8) 90)) < 0)
+ return ret;
+ }
+ else
+ {
+ if ((config_val & 0x0c) == 0x0C) //We are running 90MHz
+ if ((ret = mt312_init(i2c, id, (u8) 60)) < 0)
+ return ret;
+ }
set_tv_freq = tsa5059_set_tv_freq;
break;
case ID_MT312:
@@ -562,7 +609,7 @@ static int mt312_get_symbol_rate(struct dvb_i2c_bus *i2c, u32 *sr)
monitor = (buf[0] << 8) | buf[1];
- printk(KERN_DEBUG "sr(auto) = %u\n",
+ dprintk(KERN_DEBUG "sr(auto) = %u\n",
mt312_div(monitor * 15625, 4));
} else {
if ((ret = mt312_writereg(i2c, MON_CTRL, 0x05)) < 0)
@@ -578,9 +625,9 @@ static int mt312_get_symbol_rate(struct dvb_i2c_bus *i2c, u32 *sr)
sym_rat_op = (buf[0] << 8) | buf[1];
- printk(KERN_DEBUG "sym_rat_op=%d dec_ratio=%d\n",
+ dprintk(KERN_DEBUG "sym_rat_op=%d dec_ratio=%d\n",
sym_rat_op, dec_ratio);
- printk(KERN_DEBUG "*sr(manual) = %lu\n",
+ dprintk(KERN_DEBUG "*sr(manual) = %lu\n",
(((MT312_PLL_CLK * 8192) / (sym_rat_op + 8192)) *
2) - dec_ratio);
}
@@ -675,7 +722,7 @@ static int mt312_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
return -EOPNOTSUPP;
case FE_READ_STATUS:
- return mt312_read_status(i2c, arg);
+ return mt312_read_status(i2c, arg, (long) fe->data);
case FE_READ_BER:
return mt312_read_bercnt(i2c, arg);
@@ -702,8 +749,13 @@ static int mt312_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
return mt312_sleep(i2c);
case FE_INIT:
- return mt312_init(i2c, (long) fe->data);
-
+ //For the VP310 we should run at 60MHz when ever possible.
+ //It should be better to run the mt312 ar lower speed when ever possible, but tunning will be slower. ACCJr 09/29/03
+ if ((long)fe->data == ID_MT312)
+ return mt312_init(i2c, (long) fe->data, (u8) 90);
+ else
+ return mt312_init(i2c, (long) fe->data, (u8) 60);
+
case FE_RESET:
return mt312_reset(i2c, 0);
@@ -755,6 +807,11 @@ static void __exit mt312_module_exit(void)
module_init(mt312_module_init);
module_exit(mt312_module_exit);
+#if MT312_DEBUG != 0
+MODULE_PARM(debug,"i");
+MODULE_PARM_DESC(debug, "enable verbose debug messages");
+#endif
+
MODULE_DESCRIPTION("MT312 Satellite Channel Decoder Driver");
MODULE_AUTHOR("Andreas Oberritter <obi@saftware.de>");
MODULE_LICENSE("GPL");