moi
attached patch should fix it. I have been too busy to find proper
solution for ZL10353, though I now know how it should be done.
regards
Antti Palosaari
Dag Nygren wrote:
Hi again,
is there anything I can do to help debugging the
A-link DTU USB stick "Tuning failed" problem?
The stick seems to be the old model without the (m),
using the modules:
qt1010
zl10353
dvb_usb_gl861
dvb_usb
and now tunes to 3 of the 4 MUX:es we have here
in Espoo, Finland but no deal with one of them whatever I do.
Best
Dag
_______________________________________________
linux-dvb mailing list
linux-dvb@xxxxxxxxxxx
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb
--
|||
(0-0)
---------oOO--(_)--OOo---------------------------------------------
http://palosaari.fi/
-"Kahta asiaa en ymmärrä.. C-kielen syntaksi ja naisten logiikka.."
diff -r 496bf62d9e03 linux/drivers/media/dvb/dvb-usb/au6610.c
--- a/linux/drivers/media/dvb/dvb-usb/au6610.c Thu Nov 15 12:07:19 2007 -0200
+++ b/linux/drivers/media/dvb/dvb-usb/au6610.c Thu Nov 15 17:02:19 2007 +0200
@@ -123,10 +123,23 @@ static int au6610_identify_state(struct
return 0;
}
+static int au6610_zl10353_demod_init(struct dvb_frontend *fe)
+{
+ u8 unk1[] = { 0x8e , 0x00 };
+ u8 unk2[] = { 0x90, 0x00, 0xff, 0xff, 0x00, 0xff, 0x3f, 0x3f };
+
+ zl10353_write_(fe, unk1, sizeof(unk1));
+ zl10353_write_(fe, unk2, sizeof(unk2));
+
+ return 0;
+}
+
static struct zl10353_config au6610_zl10353_config = {
.demod_address = 0x0f,
.no_tuner = 1,
.parallel_ts = 1,
+ .agc2 = 1,
+ .demod_init = au6610_zl10353_demod_init
};
static int au6610_zl10353_frontend_attach(struct dvb_usb_adapter *adap)
diff -r 496bf62d9e03 linux/drivers/media/dvb/dvb-usb/gl861.c
--- a/linux/drivers/media/dvb/dvb-usb/gl861.c Thu Nov 15 12:07:19 2007 -0200
+++ b/linux/drivers/media/dvb/dvb-usb/gl861.c Thu Nov 15 17:02:19 2007 +0200
@@ -45,6 +45,8 @@ static int gl861_i2c_msg(struct dvb_usb_
return -EINVAL;
}
+ udelay(10); /* avoid usb i2c timeouts */
+
return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), req, type,
value, index, rbuf, rlen, 2000);
}
@@ -100,10 +102,23 @@ static int gl861_identify_state(struct u
return 0;
}
+static int gl861_zl10353_demod_init(struct dvb_frontend *fe)
+{
+ u8 unk1[] = { 0x8e , 0x00 };
+ u8 unk2[] = { 0x90, 0x00, 0xff, 0xff, 0x00, 0xff, 0x3f, 0x3f };
+
+ zl10353_write_(fe, unk1, sizeof(unk1));
+ zl10353_write_(fe, unk2, sizeof(unk2));
+
+ return 0;
+}
+
static struct zl10353_config gl861_zl10353_config = {
.demod_address = 0x0f,
.no_tuner = 1,
.parallel_ts = 1,
+ .agc2 = 1,
+ .demod_init = gl861_zl10353_demod_init
};
static int gl861_frontend_attach(struct dvb_usb_adapter *adap)
@@ -156,6 +171,7 @@ static int gl861_probe(struct usb_interf
}
static struct usb_device_id gl861_table [] = {
+// { USB_DEVICE(USB_VID_MSI, 123) },
{ USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580_55801) },
{ USB_DEVICE(USB_VID_ALINK, USB_VID_ALINK_DTU) },
{ } /* Terminating entry */
diff -r 496bf62d9e03 linux/drivers/media/dvb/frontends/qt1010.c
--- a/linux/drivers/media/dvb/frontends/qt1010.c Thu Nov 15 12:07:19 2007 -0200
+++ b/linux/drivers/media/dvb/frontends/qt1010.c Thu Nov 15 17:02:19 2007 +0200
@@ -28,7 +28,7 @@ MODULE_PARM_DESC(debug, "Turn on/off deb
#define dprintk(args...) \
do { \
- if (debug) printk(KERN_DEBUG "QT1010: " args); \
+ if (debug) printk(KERN_DEBUG "qt1010: " args); \
} while (0)
/* read single register */
@@ -42,7 +42,7 @@ static int qt1010_readreg(struct qt1010_
};
if (i2c_transfer(priv->i2c, msg, 2) != 2) {
- printk(KERN_WARNING "qt1010 I2C read failed\n");
+ printk(KERN_WARNING "qt1010: i2c read failed (reg:%02x)\n", reg);
return -EREMOTEIO;
}
return 0;
@@ -56,12 +56,13 @@ static int qt1010_writereg(struct qt1010
.flags = 0, .buf = buf, .len = 2 };
if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
- printk(KERN_WARNING "qt1010 I2C write failed\n");
+ printk(KERN_WARNING "qt1010: i2c write failed (reg:%02x val:%02x)\n", reg, val);
return -EREMOTEIO;
}
return 0;
}
+#if 0
/* dump all registers */
static void qt1010_dump_regs(struct qt1010_priv *priv)
{
@@ -71,7 +72,7 @@ static void qt1010_dump_regs(struct qt10
for (reg = 0; ; reg++) {
if (reg % 16 == 0) {
if (reg)
- printk("%s\n", buf);
+ dprintk("%s\n", buf);
sprintf(buf, "%02x: ", reg);
}
if (qt1010_readreg(priv, reg, &val) == 0)
@@ -82,333 +83,579 @@ static void qt1010_dump_regs(struct qt10
if (reg == 0x2f)
break;
}
- printk("%s\n", buf);
-}
-
-static int qt1010_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
-{
- struct qt1010_priv *priv;
+ dprintk("%s\n", buf);
+}
+#endif
+
+/* read register in the loop until mask match or timeout occurs */
+static int qt1010_readreg_looping(struct qt1010_priv *priv, u8 reg, u8 mask, u8 *val)
+{
+ int err = 0;
+ u8 tmpval;
+ unsigned long timeout;
+
+ timeout = jiffies + msecs_to_jiffies(30);
+
+ while (time_before(jiffies, timeout) && !err) {
+ err = qt1010_readreg(priv, reg, &tmpval);
+ if(tmpval & mask) break;
+ }
+ *val = tmpval;
+ return err;
+}
+
+/* write ten times value 0x80 to register 0x01 */
+static int qt1010_loop10(struct qt1010_priv *priv)
+{
int err;
- u32 freq, div, mod1, mod2;
- u8 i, tmpval, reg05;
- qt1010_i2c_oper_t rd[48] = {
- { QT1010_WR, 0x01, 0x80 },
- { QT1010_WR, 0x02, 0x3f },
- { QT1010_WR, 0x05, 0xff }, /* 02 c write */
- { QT1010_WR, 0x06, 0x44 },
- { QT1010_WR, 0x07, 0xff }, /* 04 c write */
- { QT1010_WR, 0x08, 0x08 },
- { QT1010_WR, 0x09, 0xff }, /* 06 c write */
- { QT1010_WR, 0x0a, 0xff }, /* 07 c write */
- { QT1010_WR, 0x0b, 0xff }, /* 08 c write */
- { QT1010_WR, 0x0c, 0xe1 },
- { QT1010_WR, 0x1a, 0xff }, /* 10 c write */
- { QT1010_WR, 0x1b, 0x00 },
- { QT1010_WR, 0x1c, 0x89 },
- { QT1010_WR, 0x11, 0xff }, /* 13 c write */
- { QT1010_WR, 0x12, 0xff }, /* 14 c write */
- { QT1010_WR, 0x22, 0xff }, /* 15 c write */
- { QT1010_WR, 0x1e, 0x00 },
- { QT1010_WR, 0x1e, 0xd0 },
- { QT1010_RD, 0x22, 0xff }, /* 16 c read */
- { QT1010_WR, 0x1e, 0x00 },
- { QT1010_RD, 0x05, 0xff }, /* 20 c read */
- { QT1010_RD, 0x22, 0xff }, /* 21 c read */
- { QT1010_WR, 0x23, 0xd0 },
- { QT1010_WR, 0x1e, 0x00 },
- { QT1010_WR, 0x1e, 0xe0 },
- { QT1010_RD, 0x23, 0xff }, /* 25 c read */
- { QT1010_RD, 0x23, 0xff }, /* 26 c read */
- { QT1010_WR, 0x1e, 0x00 },
- { QT1010_WR, 0x24, 0xd0 },
- { QT1010_WR, 0x1e, 0x00 },
- { QT1010_WR, 0x1e, 0xf0 },
- { QT1010_RD, 0x24, 0xff }, /* 31 c read */
- { QT1010_WR, 0x1e, 0x00 },
- { QT1010_WR, 0x14, 0x7f },
- { QT1010_WR, 0x15, 0x7f },
- { QT1010_WR, 0x05, 0xff }, /* 35 c write */
- { QT1010_WR, 0x06, 0x00 },
- { QT1010_WR, 0x15, 0x1f },
- { QT1010_WR, 0x16, 0xff },
- { QT1010_WR, 0x18, 0xff },
- { QT1010_WR, 0x1f, 0xff }, /* 40 c write */
- { QT1010_WR, 0x20, 0xff }, /* 41 c write */
- { QT1010_WR, 0x21, 0x53 },
- { QT1010_WR, 0x25, 0xff }, /* 43 c write */
- { QT1010_WR, 0x26, 0x15 },
- { QT1010_WR, 0x00, 0xff }, /* 45 c write */
- { QT1010_WR, 0x02, 0x00 },
- { QT1010_WR, 0x01, 0x00 }
- };
-
-#define FREQ1 32000000 /* 32 MHz */
-#define FREQ2 4000000 /* 4 MHz Quartz oscillator in the stick? */
-
- priv = fe->tuner_priv;
- freq = params->frequency;
- div = (freq + QT1010_OFFSET) / QT1010_STEP;
- freq = (div * QT1010_STEP) - QT1010_OFFSET;
- mod1 = (freq + QT1010_OFFSET) % FREQ1;
- mod2 = (freq + QT1010_OFFSET) % FREQ2;
- priv->bandwidth =
- (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
- priv->frequency = freq;
+ u8 i;
+ for (i = 0; i < 10; i++) {
+ if ((err = qt1010_writereg(priv, 0x01, 0x80)))
+ return err;
+ }
+ return 0;
+}
+
+/* do i2c reads / writes according to given data */
+static int qt1010_handle_i2c_oper_table(struct dvb_frontend *fe,
+ qt1010_i2c_oper_t *data, int len)
+{
+ struct qt1010_priv *priv = fe->tuner_priv;
+ int err, i;
+ u8 tmpval;
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
- /* reg 05 base value */
- if (freq < 290000000) reg05 = 0x14; /* 290 MHz */
- else if (freq < 610000000) reg05 = 0x34; /* 610 MHz */
- else if (freq < 802000000) reg05 = 0x54; /* 802 MHz */
- else reg05 = 0x74;
-
- /* 0x5 */
- rd[2].val = reg05;
-
- /* 07 - set frequency: 32 MHz scale */
- rd[4].val = (freq + QT1010_OFFSET) / FREQ1;
-
- /* 09 - changes every 8/24 MHz */
- if (mod1 < 8000000) rd[6].val = 0x1d;
- else rd[6].val = 0x1c;
-
- /* 0a - set frequency: 4 MHz scale (max 28 MHz) */
- if (mod1 < 1*FREQ2) rd[7].val = 0x09; /* +0 MHz */
- else if (mod1 < 2*FREQ2) rd[7].val = 0x08; /* +4 MHz */
- else if (mod1 < 3*FREQ2) rd[7].val = 0x0f; /* +8 MHz */
- else if (mod1 < 4*FREQ2) rd[7].val = 0x0e; /* +12 MHz */
- else if (mod1 < 5*FREQ2) rd[7].val = 0x0d; /* +16 MHz */
- else if (mod1 < 6*FREQ2) rd[7].val = 0x0c; /* +20 MHz */
- else if (mod1 < 7*FREQ2) rd[7].val = 0x0b; /* +24 MHz */
- else rd[7].val = 0x0a; /* +28 MHz */
-
- /* 0b - changes every 2/2 MHz */
- if (mod2 < 2000000) rd[8].val = 0x45;
- else rd[8].val = 0x44;
-
- /* 1a - set frequency: 125 kHz scale (max 3875 kHz)*/
- tmpval = 0x78; /* byte, overflows intentionally */
- rd[10].val = tmpval-((mod2/QT1010_STEP)*0x08);
-
- /* 11 */
- rd[13].val = 0xfd; /* TODO: correct value calculation */
-
- /* 12 */
- rd[14].val = 0x91; /* TODO: correct value calculation */
-
- /* 22 */
- if (freq < 450000000) rd[15].val = 0xd0; /* 450 MHz */
- else if (freq < 482000000) rd[15].val = 0xd1; /* 482 MHz */
- else if (freq < 514000000) rd[15].val = 0xd4; /* 514 MHz */
- else if (freq < 546000000) rd[15].val = 0xd7; /* 546 MHz */
- else if (freq < 610000000) rd[15].val = 0xda; /* 610 MHz */
- else rd[15].val = 0xd0;
-
- /* 05 */
- rd[35].val = (reg05 & 0xf0);
-
- /* 1f */
- if (mod1 < 8000000) tmpval = 0x00;
- else if (mod1 < 12000000) tmpval = 0x01;
- else if (mod1 < 16000000) tmpval = 0x02;
- else if (mod1 < 24000000) tmpval = 0x03;
- else if (mod1 < 28000000) tmpval = 0x04;
- else tmpval = 0x05;
- rd[40].val = (priv->reg1f_init_val + 0x0e + tmpval);
-
- /* 20 */
- if (mod1 < 8000000) tmpval = 0x00;
- else if (mod1 < 12000000) tmpval = 0x01;
- else if (mod1 < 20000000) tmpval = 0x02;
- else if (mod1 < 24000000) tmpval = 0x03;
- else if (mod1 < 28000000) tmpval = 0x04;
- else tmpval = 0x05;
- rd[41].val = (priv->reg20_init_val + 0x0d + tmpval);
-
- /* 25 */
- rd[43].val = priv->reg25_init_val;
-
- /* 00 */
- rd[45].val = 0x92; /* TODO: correct value calculation */
-
- dprintk("freq:%u 05:%02x 07:%02x 09:%02x 0a:%02x 0b:%02x " \
- "1a:%02x 11:%02x 12:%02x 22:%02x 05:%02x 1f:%02x " \
- "20:%02x 25:%02x 00:%02x", \
- freq, rd[2].val, rd[4].val, rd[6].val, rd[7].val, rd[8].val, \
- rd[10].val, rd[13].val, rd[14].val, rd[15].val, rd[35].val, \
- rd[40].val, rd[41].val, rd[43].val, rd[45].val);
-
- for (i = 0; i < ARRAY_SIZE(rd); i++) {
- if (rd[i].oper == QT1010_WR) {
- err = qt1010_writereg(priv, rd[i].reg, rd[i].val);
- } else { /* read is required to proper locking */
- err = qt1010_readreg(priv, rd[i].reg, &tmpval);
- }
- if (err) return err;
- }
-
- if (debug)
- qt1010_dump_regs(priv);
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
-
- return 0;
-}
-
-static int qt1010_init_meas1(struct qt1010_priv *priv,
- u8 oper, u8 reg, u8 reg_init_val, u8 *retval)
-{
- u8 i, val1, val2;
- int err;
-
- qt1010_i2c_oper_t i2c_data[] = {
- { QT1010_WR, reg, reg_init_val },
- { QT1010_WR, 0x1e, 0x00 },
- { QT1010_WR, 0x1e, oper },
- { QT1010_RD, reg, 0xff }
- };
-
- for (i = 0; i < ARRAY_SIZE(i2c_data); i++) {
- if (i2c_data[i].oper == QT1010_WR) {
- err = qt1010_writereg(priv, i2c_data[i].reg,
- i2c_data[i].val);
- } else {
- err = qt1010_readreg(priv, i2c_data[i].reg, &val2);
- }
- if (err) return err;
- }
-
- do {
- val1 = val2;
- err = qt1010_readreg(priv, reg, &val2);
- if (err) return err;
- dprintk("compare reg:%02x %02x %02x", reg, val1, val2);
- } while (val1 != val2);
- *retval = val1;
-
- return qt1010_writereg(priv, 0x1e, 0x00);
-}
-
-static u8 qt1010_init_meas2(struct qt1010_priv *priv,
- u8 reg_init_val, u8 *retval)
-{
- u8 i, val;
- int err;
- qt1010_i2c_oper_t i2c_data[] = {
- { QT1010_WR, 0x07, reg_init_val },
- { QT1010_WR, 0x22, 0xd0 },
- { QT1010_WR, 0x1e, 0x00 },
- { QT1010_WR, 0x1e, 0xd0 },
- { QT1010_RD, 0x22, 0xff },
- { QT1010_WR, 0x1e, 0x00 },
- { QT1010_WR, 0x22, 0xff }
- };
- for (i = 0; i < ARRAY_SIZE(i2c_data); i++) {
- if (i2c_data[i].oper == QT1010_WR) {
- err = qt1010_writereg(priv, i2c_data[i].reg,
- i2c_data[i].val);
- } else {
- err = qt1010_readreg(priv, i2c_data[i].reg, &val);
- }
- if (err) return err;
- }
- *retval = val;
- return 0;
-}
-
-static int qt1010_init(struct dvb_frontend *fe)
-{
- struct qt1010_priv *priv = fe->tuner_priv;
- struct dvb_frontend_parameters params;
- int err = 0;
- u8 i, tmpval, *valptr = NULL;
-
- qt1010_i2c_oper_t i2c_data[] = {
- { QT1010_WR, 0x01, 0x80 },
- { QT1010_WR, 0x0d, 0x84 },
- { QT1010_WR, 0x0e, 0xb7 },
- { QT1010_WR, 0x2a, 0x23 },
- { QT1010_WR, 0x2c, 0xdc },
- { QT1010_M1, 0x25, 0x40 }, /* get reg 25 init value */
- { QT1010_M1, 0x81, 0xff }, /* get reg 25 init value */
- { QT1010_WR, 0x2b, 0x70 },
- { QT1010_WR, 0x2a, 0x23 },
- { QT1010_M1, 0x26, 0x08 },
- { QT1010_M1, 0x82, 0xff },
- { QT1010_WR, 0x05, 0x14 },
- { QT1010_WR, 0x06, 0x44 },
- { QT1010_WR, 0x07, 0x28 },
- { QT1010_WR, 0x08, 0x0b },
- { QT1010_WR, 0x11, 0xfd },
- { QT1010_M1, 0x22, 0x0d },
- { QT1010_M1, 0xd0, 0xff },
- { QT1010_WR, 0x06, 0x40 },
- { QT1010_WR, 0x16, 0xf0 },
- { QT1010_WR, 0x02, 0x38 },
- { QT1010_WR, 0x03, 0x18 },
- { QT1010_WR, 0x20, 0xe0 },
- { QT1010_M1, 0x1f, 0x20 }, /* get reg 1f init value */
- { QT1010_M1, 0x84, 0xff }, /* get reg 1f init value */
- { QT1010_RD, 0x20, 0x20 }, /* get reg 20 init value */
- { QT1010_WR, 0x03, 0x19 },
- { QT1010_WR, 0x02, 0x3f },
- { QT1010_WR, 0x21, 0x53 },
- { QT1010_RD, 0x21, 0xff },
- { QT1010_WR, 0x11, 0xfd },
- { QT1010_WR, 0x05, 0x34 },
- { QT1010_WR, 0x06, 0x44 },
- { QT1010_WR, 0x08, 0x08 }
- };
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
-
- for (i = 0; i < ARRAY_SIZE(i2c_data); i++) {
- switch (i2c_data[i].oper) {
- case QT1010_WR:
- err = qt1010_writereg(priv, i2c_data[i].reg,
- i2c_data[i].val);
+ for (i = 0; i < len; i++) {
+ switch (data[i].oper) {
+ case QT1010_WRITE:
+ err = qt1010_writereg(priv, data[i].reg, data[i].val);
break;
- case QT1010_RD:
- if (i2c_data[i].val == 0x20)
- valptr = &priv->reg20_init_val;
- else
- valptr = &tmpval;
- err = qt1010_readreg(priv, i2c_data[i].reg, valptr);
+ case QT1010_READ:
+ err = qt1010_readreg(priv, data[i].reg, &tmpval);
break;
- case QT1010_M1:
- if (i2c_data[i].val == 0x25)
- valptr = &priv->reg25_init_val;
- else if (i2c_data[i].val == 0x1f)
- valptr = &priv->reg1f_init_val;
- else
- valptr = &tmpval;
- err = qt1010_init_meas1(priv, i2c_data[i+1].reg,
- i2c_data[i].reg,
- i2c_data[i].val, valptr);
- i++;
+ case QT1010_READLOOP:
+ err = qt1010_readreg_looping(priv, data[i].reg, data[i].val, &tmpval);
+ break;
+ case QT1010_READ22:
+ err = qt1010_readreg(priv, data[i].reg, &tmpval);
+ if(tmpval < 0xff)
+ err = qt1010_writereg(priv, 0x22, tmpval + 1);
+ break;
+ case QT1010_LOOP10:
+ err = qt1010_loop10(priv);
break;
}
if (err) return err;
- }
-
- for (i = 0x31; i < 0x3a; i++) /* 0x31 - 0x39 */
- if ((err = qt1010_init_meas2(priv, i, &tmpval)))
- return err;
-
- params.frequency = 545000000; /* Sigmatek DVB-110 545000000 */
- /* MSI Megasky 580 GL861 533000000 */
- return qt1010_set_params(fe, ¶ms);
+ if (data[i].retval != NULL)
+ *data[i].retval = tmpval;
+ }
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
+
+ return 0;
+}
+
+/* calculates register values needed for tuning to channel */
+static int qt1010_calc_regs(struct dvb_frontend *fe, u8 oper,
+ chanset_regs_t *chanset)
+{
+ struct qt1010_priv *priv = fe->tuner_priv;
+ u32 f_rf, f_if, f_if1, f_if2, f_lo1, f_lo2, f_lo3;
+ u32 div1, num1a, num1b, div2, num2a, num2b, div3, num3x, div3b;
+ u8 do_band_switch = 0;
+ static u8 previous_oper;
+ f_rf = priv->frequency;
+
+ /* override default IF if needed (~30-60 MHz) */
+ if (priv->cfg->if_freq)
+ f_if = priv->cfg->if_freq;
+ else
+ f_if = 36125000; /* defaults to 36.125 MHz */
+
+ if(oper == QT1010_OPER_BAND) {
+ oper = previous_oper;
+ do_band_switch = 1;
+ } else
+ previous_oper = oper;
+
+ f_if1 = 1232000000;
+ f_lo1 = f_rf + f_if1;
+ div1 = 500000 + f_lo1 / 4;
+ div1 /= 1000000;
+ div1 *= 1000000;
+ num1a = (div1 / 1000000) / 8;
+ num1b = (div1 / 1000000) % 8;
+ f_if1 = div1 * 4 - f_rf;
+
+ f_lo2 = 920000000;
+ f_if2 = f_if1 - f_lo2;
+ div2 = f_lo2 / 4;
+ div2 /= 1000000;
+ div2 *= 1000000;
+ num2a = (div2 / 1000000) / 8;
+ num2b = (div2 / 1000000) % 8;
+
+ f_lo3 = f_if2 - f_if;
+ div3 = f_lo3 / 4;
+ div3b = div3 / 1000000;
+ num3x = (500000 + ((div3 - div3b * 1000000) * 256)) / 1000000;
+
+ dprintk("%s: div1:%d num1a:%d num1b:%d div2:%d num2a:%d num2b:%d div3:%d\n",
+ __FUNCTION__, div1, num1a, num1b, div2, num2a, num2b, div3);
+
+ if(num3x > 255) chanset->reg1a = num3x % 256;
+ else chanset->reg1a = num3x;
+
+ chanset->reg1c = 137 + (num3x / 256) * 2;
+ chanset->reg0b = div3b;
+
+ if(oper == QT1010_OPER_EA) {
+ switch(num1b) {
+ case 0:
+ chanset->reg1f = 0x09;
+ chanset->reg20 = 0x0a;
+ break;
+ case 1:
+ chanset->reg1f = 0x0a;
+ chanset->reg20 = 0x0a;
+ break;
+ case 2:
+ chanset->reg1f = 0x0a;
+ chanset->reg20 = 0x0b;
+ break;
+ case 3:
+ chanset->reg1f = 0x0b;
+ chanset->reg20 = 0x0c;
+ break;
+ case 4:
+ chanset->reg1f = 0x0c;
+ chanset->reg20 = 0x0c;
+ break;
+ case 5:
+ chanset->reg1f = 0x0d;
+ chanset->reg20 = 0x0d;
+ break;
+ case 6:
+ chanset->reg1f = 0x0d;
+ chanset->reg20 = 0x0d;
+ break;
+ case 7:
+ chanset->reg1f = 0x0f;
+ chanset->reg20 = 0x0e;
+ break;
+ default:
+ chanset->reg1f = 0x00;
+ chanset->reg20 = 0x00;
+ break;
+ }
+ } else if(oper == QT1010_OPER_FF) {
+ switch(num1b) {
+ case 0:
+ chanset->reg1f = 0x16;
+ chanset->reg20 = 0x15;
+ break;
+ case 1:
+ chanset->reg1f = 0x11;
+ chanset->reg20 = 0x0f;
+ break;
+ case 2:
+ chanset->reg1f = 0x11;
+ chanset->reg20 = 0x10;
+ break;
+ case 3:
+ chanset->reg1f = 0x12;
+ chanset->reg20 = 0x11;
+ break;
+ case 4:
+ chanset->reg1f = 0x13;
+ chanset->reg20 = 0x12;
+ break;
+ case 5:
+ chanset->reg1f = 0x14;
+ chanset->reg20 = 0x13;
+ break;
+ case 6:
+ chanset->reg1f = 0x15;
+ chanset->reg20 = 0x13;
+ break;
+ case 7:
+ chanset->reg1f = 0x16;
+ chanset->reg20 = 0x14;
+ break;
+ default:
+ chanset->reg1f = 0x00;
+ chanset->reg20 = 0x00;
+ break;
+ }
+ } else {
+ switch(num1b) {
+ case 0:
+ chanset->reg1f = 0x10;
+ chanset->reg20 = 0x0f;
+ break;
+ case 1:
+ chanset->reg1f = 0x11;
+ chanset->reg20 = 0x0f;
+ break;
+ case 2:
+ chanset->reg1f = 0x11;
+ chanset->reg20 = 0x10;
+ break;
+ case 3:
+ chanset->reg1f = 0x12;
+ chanset->reg20 = 0x11;
+ break;
+ case 4:
+ chanset->reg1f = 0x13;
+ chanset->reg20 = 0x12;
+ break;
+ case 5:
+ chanset->reg1f = 0x0d;
+ chanset->reg20 = 0x0d;
+ break;
+ case 6:
+ chanset->reg1f = 0x0d;
+ chanset->reg20 = 0x0d;
+ break;
+ case 7:
+ chanset->reg1f = 0x0f;
+ chanset->reg20 = 0x0e;
+ break;
+ default:
+ chanset->reg1f = 0x00;
+ chanset->reg20 = 0x00;
+ break;
+ }
+ }
+ chanset->reg1f += priv->init.reg1f;
+ chanset->reg20 += priv->init.reg20;
+
+ div1 /= 1000000;
+ if(oper == QT1010_OPER_EA) {
+ if(num1b > 0) div1 += (8 - num1b);
+ else div1 += 8;
+ } else if(oper == QT1010_OPER_FF) {
+ if(num1b > 0) div1 -= num1b;
+ else div1 -= 8;
+ } else {
+ if(num1b > 4) div1 += (8 - num1b);
+ else div1 -= num1b;
+ }
+ div1 *= 1000000;
+
+ f_if1 = div1 * 4 - (f_rf / 1000000) * 1000000;
+ f_lo1 = f_rf + f_if1;
+ f_lo2 = f_if1 - f_if2;
+ div2 = f_lo2 / 4;
+ num1a = (div1 / 1000000) / 8;
+ num1b = (div1 / 1000000) % 8;
+ num2a = (div2 / 1000000) / 8;
+ num2b = (div2 / 1000000) % 8;
+
+ chanset->reg07 = num1a;
+ chanset->reg08 = num1b + 8;
+ chanset->reg09 = num2a;
+ chanset->reg0a = num2b + 8;
+
+ dprintk("%s: div1:%d num1a:%d num1b:%d div2:%d num2a:%d num2b:%d div3:%d\n",
+ __FUNCTION__, div1, num1a, num1b, div2, num2a, num2b, div3);
+
+ /* band setting */
+ if (f_lo1 < 1600000000) chanset->reg05 = 0x14;
+ else if(f_lo1 < 1856000000) chanset->reg05 = 0x34;
+ else if(f_lo1 < 2080000000) chanset->reg05 = 0x54;
+ else chanset->reg05 = 0x74;
+
+ switch((f_lo1 / 1000000)) {
+ case 1568: chanset->reg22 = priv->init.reg22_1; break;
+ case 1600: chanset->reg22 = priv->init.reg22_2; break;
+ case 1632: chanset->reg22 = priv->init.reg22_3; break;
+ case 1664: chanset->reg22 = priv->init.reg22_4; break;
+ case 1696: chanset->reg22 = priv->init.reg22_5; break;
+ case 1728: chanset->reg22 = priv->init.reg22_6; break;
+ case 1760: chanset->reg22 = priv->init.reg22_7; break;
+ case 1792: chanset->reg22 = priv->init.reg22_8; break;
+ case 1824: chanset->reg22 = priv->init.reg22_9; break;
+ default: chanset->reg22 = 0xd0; break;
+ }
+
+ if(chanset->reg05 == 0x34) {
+ if(chanset->reg22 < 0xf0)
+ chanset->reg22 = 0xd0;
+ else if(chanset->reg22 > 0xfa)
+ chanset->reg22 = 0xda;
+ else
chanset->reg22 -= 0x20;
+ } else
+ chanset->reg22 = 0xd0;
+
+ if(do_band_switch)
+ if(chanset->oper_reg05 < 0x74) /* 0x14 or 0x34 or 0x54 */
+ chanset->reg05 = chanset->oper_reg05 + 0x20; /* 0x14 => 0x34 => 0x54 => 0x74 */
+
+ chanset->reg11 = 0xfd;
+#if 0
+ /* MSI Megasky 580 gl861 does this */
+ if(chanset->reg05 < 0x54)
+ chanset->reg11 = 0xfd;
+ else
+ chanset->reg11 = 0xf9;
+#endif
+#if 1
+ dprintk("%s: %d 05:%02x 07:%02x 08:%02x 09:%02x 0a:%02x " \
+ "0b:%02x 1a:%02x 1c:%02x 22:%02x 1f:%02x 20:%02x 11:%02x\n", \
+ __FUNCTION__, f_rf, chanset->reg05, chanset->reg07, chanset->reg08, \
+ chanset->reg09, chanset->reg0a, chanset->reg0b, chanset->reg1a, \
+ chanset->reg1c, chanset->reg22, chanset->reg1f, chanset->reg20, \
+ chanset->reg11);
+#endif
+ return 0;
+}
+
+static int qt1010_chanset(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *params,
+ chanset_regs_t *chanset, u8 oper)
+{
+ struct qt1010_priv *priv = fe->tuner_priv;
+ int err = qt1010_calc_regs(fe, oper, chanset);
+ qt1010_i2c_oper_t data[] = {
+ { QT1010_WRITE, 0x01, 0x80, NULL },
+ { QT1010_WRITE, 0x02, 0x3f, NULL },
+ { QT1010_WRITE, 0x05, chanset->reg05, NULL },
+ { QT1010_WRITE, 0x06, 0x44, NULL },
+ { QT1010_WRITE, 0x07, chanset->reg07, NULL },
+ { QT1010_WRITE, 0x08, chanset->reg08, NULL },
+ { QT1010_WRITE, 0x09, chanset->reg09, NULL },
+ { QT1010_WRITE, 0x0a, chanset->reg0a, NULL },
+ { QT1010_WRITE, 0x0b, chanset->reg0b, NULL },
+ { QT1010_WRITE, 0x0c, 0xe1, NULL },
+ { QT1010_WRITE, 0x1a, chanset->reg1a, NULL },
+ { QT1010_WRITE, 0x1b, 0x00, NULL },
+ { QT1010_WRITE, 0x1c, chanset->reg1c, NULL },
+ { QT1010_WRITE, 0x11, chanset->reg11, NULL },
+ { QT1010_LOOP10, NA , NA , NULL },
+ { QT1010_WRITE, 0x12, 0x95, NULL },
+ { QT1010_WRITE, 0x22, chanset->reg22, NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_WRITE, 0x1e, 0xd0, NULL },
+ { QT1010_READ22, 0x22, NA , NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_READ, 0x05, NA , &chanset->oper_reg05 },
+ { QT1010_READ, 0x22, NA , &chanset->oper_reg22 },
+ { QT1010_WRITE, 0x23, 0xd0, NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_WRITE, 0x1e, 0xe0, NULL },
+ { QT1010_READLOOP, 0x23, 0x20, &chanset->oper_reg23 },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_WRITE, 0x24, 0xd0, NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_WRITE, 0x1e, 0xf0, NULL },
+ { QT1010_READLOOP, 0x24, 0x20, NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_WRITE, 0x14, 0x7f, NULL },
+ { QT1010_WRITE, 0x15, 0x7f, NULL },
+ { QT1010_WRITE, 0x05, chanset->reg05 - 0x04, NULL },
+ { QT1010_WRITE, 0x06, 0x00, NULL },
+ { QT1010_WRITE, 0x15, 0x1f, NULL },
+ { QT1010_WRITE, 0x16, 0xff, NULL },
+ { QT1010_WRITE, 0x18, 0xff, NULL },
+ { QT1010_WRITE, 0x1f, chanset->reg1f, NULL },
+ { QT1010_WRITE, 0x20, chanset->reg20, NULL },
+ { QT1010_WRITE, 0x21, priv->init.reg21, NULL },
+ { QT1010_WRITE, 0x25, priv->init.reg25, NULL },
+ { QT1010_WRITE, 0x26, priv->init.reg26, NULL },
+ { QT1010_WRITE, 0x00, 0x81, NULL },
+ { QT1010_WRITE, 0x02, 0x00, NULL },
+ { QT1010_WRITE, 0x01, 0x00, NULL }
+ };
+
+ if (err) return err;
+
+#if 0
+ dprintk("%s: %d 05:%02x 07:%02x 08:%02x 09:%02x 0a:%02x 0b:%02x " \
+ "1a:%02x 1c:%02x 22:%02x 1f:%02x 20:%02x 11:%02x 05:%02x 25:%02x\n", \
+ __FUNCTION__, priv->frequency, data[2].val, data[4].val, \
+ data[5].val, data[6].val, data[7].val, data[8].val, data[10].val, \
+ data[12].val, data[16].val, data[40].val, data[41].val, \
+ data[13].val, data[35].val, data[43].val);
+#endif
+ return qt1010_handle_i2c_oper_table(fe, data, ARRAY_SIZE(data));
+}
+
+static int qt1010_set_params(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *params)
+{
+ struct qt1010_priv *priv = fe->tuner_priv;
+ int err;
+ chanset_regs_t chanset;
+ priv->frequency = (params->frequency / QT1010_STEP) * QT1010_STEP;
+ priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
+
+ err = qt1010_chanset(fe, params, &chanset, QT1010_OPER_NORMAL);
+ if(chanset.oper_reg23 <= 0xea && !err)
+ err = qt1010_chanset(fe, params, &chanset, QT1010_OPER_EA);
+ if(chanset.oper_reg23 == 0xff && !err)
+ err = qt1010_chanset(fe, params, &chanset, QT1010_OPER_FF);
+ if(chanset.oper_reg22 == 0xff && !err)
+ err = qt1010_chanset(fe, params, &chanset, QT1010_OPER_BAND);
+
+ return err;
+}
+
+static int qt1010_init(struct dvb_frontend *fe)
+{
+ int err;
+ struct qt1010_priv *priv = fe->tuner_priv;
+ qt1010_i2c_oper_t data[] = {
+ { QT1010_WRITE, 0x01, 0x80, NULL },
+ { QT1010_WRITE, 0x0d, 0x84, NULL },
+ { QT1010_WRITE, 0x0e, 0xb7, NULL },
+// { QT1010_WRITE, 0x0e, 0xb4, NULL },
+ { QT1010_WRITE, 0x2a, 0x23, NULL },
+ { QT1010_WRITE, 0x2c, 0xdc, NULL },
+ { QT1010_WRITE, 0x25, 0x40, NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_WRITE, 0x1e, 0x81, NULL },
+ { QT1010_READLOOP, 0x25, 0x80, &priv->init.reg25 },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_WRITE, 0x2a, 0x23, NULL },
+ { QT1010_WRITE, 0x2b, 0x70, NULL },
+ { QT1010_WRITE, 0x26, 0x08, NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_WRITE, 0x1e, 0x82, NULL },
+ { QT1010_READLOOP, 0x26, 0x10, &priv->init.reg26 },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_WRITE, 0x05, 0x14, NULL },
+ { QT1010_WRITE, 0x06, 0x44, NULL },
+ { QT1010_WRITE, 0x07, 0x28, NULL },
+ { QT1010_WRITE, 0x08, 0x0b, NULL },
+ { QT1010_WRITE, 0x11, 0xf9, NULL },
+ { QT1010_LOOP10, NA , NA , NULL },
+ { QT1010_WRITE, 0x22, 0x0d, NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_WRITE, 0x1e, 0xd0, NULL },
+ { QT1010_READLOOP, 0x22, 0x20, NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_WRITE, 0x06, 0x40, NULL },
+ { QT1010_WRITE, 0x16, 0xf0, NULL },
+ { QT1010_WRITE, 0x02, 0x38, NULL },
+ { QT1010_WRITE, 0x03, 0x18, NULL },
+ { QT1010_WRITE, 0x1f, 0x20, NULL },
+ { QT1010_WRITE, 0x20, 0xe0, NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_WRITE, 0x1e, 0x84, NULL },
+ { QT1010_READLOOP, 0x1f, 0x40, &priv->init.reg1f },
+ { QT1010_READ, 0x20, NA , &priv->init.reg20 },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_WRITE, 0x03, 0x19, NULL },
+ { QT1010_WRITE, 0x02, 0x3f, NULL },
+ { QT1010_WRITE, 0x21, 0x53, NULL },
+ { QT1010_READ, 0x21, NA , &priv->init.reg21 },
+ { QT1010_WRITE, 0x11, 0xfd, NULL },
+ { QT1010_WRITE, 0x05, 0x34, NULL },
+ { QT1010_WRITE, 0x06, 0x44, NULL },
+ { QT1010_WRITE, 0x07, 0x31, NULL },
+ { QT1010_WRITE, 0x08, 0x08, NULL },
+ { QT1010_WRITE, 0x22, 0xd0, NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_WRITE, 0x1e, 0xd0, NULL },
+ { QT1010_READLOOP, 0x22, 0x20, NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_READ, 0x22, NA , &priv->init.reg22_1 },
+ { QT1010_WRITE, 0x07, 0x32, NULL },
+ { QT1010_WRITE, 0x22, 0xd0, NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_WRITE, 0x1e, 0xd0, NULL },
+ { QT1010_READLOOP, 0x22, 0x20, NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_READ, 0x22, NA , &priv->init.reg22_2 },
+ { QT1010_WRITE, 0x07, 0x33, NULL },
+ { QT1010_WRITE, 0x22, 0xd0, NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_WRITE, 0x1e, 0xd0, NULL },
+ { QT1010_READLOOP, 0x22, 0x20, NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_READ, 0x22, NA , &priv->init.reg22_3 },
+ { QT1010_WRITE, 0x07, 0x34, NULL },
+ { QT1010_WRITE, 0x22, 0xd0, NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_WRITE, 0x1e, 0xd0, NULL },
+ { QT1010_READLOOP, 0x22, 0x20, NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_READ, 0x22, NA , &priv->init.reg22_4 },
+ { QT1010_WRITE, 0x07, 0x35, NULL },
+ { QT1010_WRITE, 0x22, 0xd0, NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_WRITE, 0x1e, 0xd0, NULL },
+ { QT1010_READLOOP, 0x22, 0x20, NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_READ, 0x22, NA , &priv->init.reg22_5 },
+ { QT1010_WRITE, 0x07, 0x36, NULL },
+ { QT1010_WRITE, 0x22, 0xd0, NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_WRITE, 0x1e, 0xd0, NULL },
+ { QT1010_READLOOP, 0x22, 0x20, NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_READ, 0x22, NA , &priv->init.reg22_6 },
+ { QT1010_WRITE, 0x07, 0x37, NULL },
+ { QT1010_WRITE, 0x22, 0xd0, NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_WRITE, 0x1e, 0xd0, NULL },
+ { QT1010_READLOOP, 0x22, 0x20, NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_READ, 0x22, NA , &priv->init.reg22_7 },
+ { QT1010_WRITE, 0x07, 0x38, NULL },
+ { QT1010_WRITE, 0x22, 0xd0, NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_WRITE, 0x1e, 0xd0, NULL },
+ { QT1010_READLOOP, 0x22, 0x20, NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_READ, 0x22, NA , &priv->init.reg22_8 },
+ { QT1010_WRITE, 0x07, 0x39, NULL },
+ { QT1010_WRITE, 0x22, 0xd0, NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_WRITE, 0x1e, 0xd0, NULL },
+ { QT1010_READLOOP, 0x22, 0x20, NULL },
+ { QT1010_WRITE, 0x1e, 0x00, NULL },
+ { QT1010_READ, 0x22, NA , &priv->init.reg22_9 }
+ };
+
+ err = qt1010_handle_i2c_oper_table(fe, data, ARRAY_SIZE(data));
+
+#if 1
+ dprintk("%s: 1f:%02x 20:%02x 21:%02x 25:%02x 26:%02x " \
+ "22_1:%02x 22_2:%02x 22_3:%02x 22_4:%02x 22_5:%02x " \
+ "22_6:%02x 22_7:%02x 22_8:%02x 22_9:%02x\n", \
+ __FUNCTION__, priv->init.reg1f, priv->init.reg20, priv->init.reg21, \
+ priv->init.reg25, priv->init.reg26, priv->init.reg22_1, \
+ priv->init.reg22_2, priv->init.reg22_3, priv->init.reg22_4, \
+ priv->init.reg22_5, priv->init.reg22_6, priv->init.reg22_7, \
+ priv->init.reg22_8, priv->init.reg22_9);
+#endif
+ return err;
+}
+
+static int qt1010_sleep(struct dvb_frontend *fe)
+{
+ qt1010_i2c_oper_t data[] = {
+ { QT1010_WRITE, 0x01, 0x80, NULL },
+ { QT1010_WRITE, 0x02, 0x7f, NULL },
+ { QT1010_READ, 0x05, NA , NULL },
+ { QT1010_WRITE, 0x05, 0x01, NULL },
+ { QT1010_WRITE, 0x06, 0xff, NULL },
+ { QT1010_WRITE, 0x01, 0x00, NULL }
+ };
+ return qt1010_handle_i2c_oper_table(fe, data, ARRAY_SIZE(data));
}
static int qt1010_release(struct dvb_frontend *fe)
{
- kfree(fe->tuner_priv);
- fe->tuner_priv = NULL;
+ if (fe != NULL) {
+ kfree(fe->tuner_priv);
+ fe->tuner_priv = NULL;
+ }
return 0;
}
@@ -436,8 +683,7 @@ static const struct dvb_tuner_ops qt1010
.release = qt1010_release,
.init = qt1010_init,
- /* TODO: implement sleep */
-
+ .sleep = qt1010_sleep,
.set_params = qt1010_set_params,
.get_frequency = qt1010_get_frequency,
.get_bandwidth = qt1010_get_bandwidth
diff -r 496bf62d9e03 linux/drivers/media/dvb/frontends/qt1010.h
--- a/linux/drivers/media/dvb/frontends/qt1010.h Thu Nov 15 12:07:19 2007 -0200
+++ b/linux/drivers/media/dvb/frontends/qt1010.h Thu Nov 15 17:02:19 2007 +0200
@@ -25,7 +25,8 @@
#include "dvb_frontend.h"
struct qt1010_config {
- u8 i2c_address;
+ u8 i2c_address;
+ u32 if_freq; /* defaults to 36.125 MHz */
};
/**
diff -r 496bf62d9e03 linux/drivers/media/dvb/frontends/qt1010_priv.h
--- a/linux/drivers/media/dvb/frontends/qt1010_priv.h Thu Nov 15 12:07:19 2007 -0200
+++ b/linux/drivers/media/dvb/frontends/qt1010_priv.h Thu Nov 15 17:02:19 2007 +0200
@@ -30,20 +30,20 @@ 02 00 ?
02 00 ?
03 19 ?
04 00 ?
-05 00 ? maybe band selection
+05 00 band selection
06 00 ?
07 2b set frequency: 32 MHz scale, n*32 MHz
-08 0b ?
-09 10 ? changes every 8/24 MHz; values 1d/1c
+08 0b set frequency
+09 10 set frequency
0a 08 set frequency: 4 MHz scale, n*4 MHz
-0b 41 ? changes every 2/2 MHz; values 45/45
+0b 41 set frequency
0c e1 ?
0d 94 ?
0e b6 ?
0f 2c ?
10 10 ?
-11 f1 ? maybe device specified adjustment
-12 11 ? maybe device specified adjustment
+11 f1 clock
+12 11 ? P3
13 3f ?
14 1f ?
15 3f ?
@@ -53,17 +53,17 @@ 19 80 ?
19 80 ?
1a d0 set frequency: 125 kHz scale, n*125 kHz
1b 00 ?
-1c 89 ?
+1c 89 set frequency
1d 00 ?
1e 00 ? looks like operation register; write cmd here, read result from 1f-26
-1f 20 ? chip initialization
-20 e0 ? chip initialization
-21 20 ?
-22 d0 ?
-23 d0 ?
-24 d0 ?
-25 40 ? chip initialization
-26 08 ?
+1f 20 chip initialization / calibration
+20 e0 chip initialization / calibration
+21 20 chip initialization / calibration
+22 d0 ? used when tuning to freq
+23 d0 ? used when tuning to freq
+24 d0 ? chip initialization / calibration
+25 40 chip initialization / calibration
+26 08 chip initialization / calibration
27 29 ?
28 55 ?
29 39 ?
@@ -75,28 +75,71 @@ 2f 00 ? not used?
2f 00 ? not used?
*/
-#define QT1010_STEP 125000 /* 125 kHz used by Windows drivers,
- hw could be more precise but we don't
- know how to use */
+#define QT1010_STEP 125000 /* 125 kHz */
#define QT1010_MIN_FREQ 48000000 /* 48 MHz */
#define QT1010_MAX_FREQ 860000000 /* 860 MHz */
#define QT1010_OFFSET 1246000000 /* 1246 MHz */
-#define QT1010_WR 0
-#define QT1010_RD 1
-#define QT1010_M1 3
+
+enum qt1010_constants {
+ QT1010_READ,
+ QT1010_WRITE,
+ QT1010_READLOOP,
+ QT1010_LOOP10,
+ QT1010_READ22,
+
+ QT1010_OPER_NORMAL,
+ QT1010_OPER_EA,
+ QT1010_OPER_FF,
+ QT1010_OPER_BAND,
+
+ NA
+};
typedef struct {
- u8 oper, reg, val;
+ u8 oper, reg, val, *retval;
} qt1010_i2c_oper_t;
+
+typedef struct {
+ u8 reg1f;
+ u8 reg20;
+ u8 reg21;
+ u8 reg25;
+ u8 reg26;
+ u8 reg22_1;
+ u8 reg22_2;
+ u8 reg22_3;
+ u8 reg22_4;
+ u8 reg22_5;
+ u8 reg22_6;
+ u8 reg22_7;
+ u8 reg22_8;
+ u8 reg22_9;
+} init_regs_t;
+
+typedef struct {
+ u8 reg05;
+ u8 reg07;
+ u8 reg08;
+ u8 reg09;
+ u8 reg0a;
+ u8 reg0b;
+ u8 reg1a;
+ u8 reg1c;
+ u8 reg22;
+ u8 reg1f;
+ u8 reg20;
+ u8 reg11;
+ u8 oper_reg05;
+ u8 oper_reg22;
+ u8 oper_reg23;
+} chanset_regs_t;
struct qt1010_priv {
struct qt1010_config *cfg;
struct i2c_adapter *i2c;
- u8 reg1f_init_val;
- u8 reg20_init_val;
- u8 reg25_init_val;
+ init_regs_t init;
u32 frequency;
u32 bandwidth;
diff -r 496bf62d9e03 linux/drivers/media/dvb/frontends/zl10353.c
--- a/linux/drivers/media/dvb/frontends/zl10353.c Thu Nov 15 12:07:19 2007 -0200
+++ b/linux/drivers/media/dvb/frontends/zl10353.c Thu Nov 15 17:02:19 2007 +0200
@@ -21,6 +21,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/string.h>
@@ -123,106 +124,84 @@ static void zl10353_dump_regs(struct dvb
}
#endif
-static void zl10353_calc_nominal_rate(struct dvb_frontend *fe,
- enum fe_bandwidth bandwidth,
- u16 *nominal_rate)
-{
- u32 adc_clock = 22528; /* 20.480 MHz on the board(!?) */
- u8 bw;
- struct zl10353_state *state = fe->demodulator_priv;
-
- if (state->config.adc_clock)
- adc_clock = state->config.adc_clock;
-
- switch (bandwidth) {
+static int zl10353_sleep(struct dvb_frontend *fe)
+{
+ static u8 zl10353_softdown[] = { CONFIG, 0x0C, 0x44 };
+ zl10353_write(fe, zl10353_softdown, sizeof(zl10353_softdown));
+ return 0;
+}
+
+static int zl10353_set_parameters(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *param)
+{
+ struct zl10353_state *state = fe->demodulator_priv;
+ struct dvb_ofdm_parameters *op = ¶m->u.ofdm;
+ u16 nominal_rate;
+ u8 bw, bw_ctrl;
+ u8 pllbuf[6] = { 0x67 };
+ u32 adc_clock = 20480; /* default 20.480 MHz */
+
+ switch (op->bandwidth) {
case BANDWIDTH_6_MHZ:
bw = 6;
+ bw_ctrl = 0x34;
break;
case BANDWIDTH_7_MHZ:
bw = 7;
+ bw_ctrl = 0x35;
break;
case BANDWIDTH_8_MHZ:
default:
bw = 8;
+ bw_ctrl = 0x36;
break;
}
- *nominal_rate = (64 * bw * (1<<16) / (7 * 8) * 4000 / adc_clock + 2) / 4;
-
+ if (state->config.adc_clock)
+ adc_clock = state->config.adc_clock;
+
+ nominal_rate = (64 * bw * (1<<16) / (7 * 8) * 4000 / (adc_clock + 2048) + 2) / 4;
dprintk("%s: bw %d, adc_clock %d => 0x%x\n",
- __FUNCTION__, bw, adc_clock, *nominal_rate);
-}
-
-static int zl10353_sleep(struct dvb_frontend *fe)
-{
- static u8 zl10353_softdown[] = { 0x50, 0x0C, 0x44 };
-
- zl10353_write(fe, zl10353_softdown, sizeof(zl10353_softdown));
- return 0;
-}
-
-static int zl10353_set_parameters(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *param)
-{
- struct zl10353_state *state = fe->demodulator_priv;
- u16 nominal_rate;
- 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_calc_nominal_rate(fe, param->u.ofdm.bandwidth, &nominal_rate);
+ __FUNCTION__, bw, adc_clock, nominal_rate);
+
+ zl10353_single_write(fe, BW_CTL, bw_ctrl);
zl10353_single_write(fe, TRL_NOMINAL_RATE_1, msb(nominal_rate));
zl10353_single_write(fe, TRL_NOMINAL_RATE_0, lsb(nominal_rate));
- zl10353_single_write(fe, 0x6C, 0xCD);
- zl10353_single_write(fe, 0x6D, 0x7E);
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
-
- // if there is no attached secondary tuner, we call set_params to program
- // a potential tuner attached somewhere else
+ /* 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 pllbuf is defined, retrieve the settings
- if (fe->ops.tuner_ops.calc_regs) {
- fe->ops.tuner_ops.calc_regs(fe, param, pllbuf+1, 5);
- pllbuf[1] <<= 1;
+ zl10353_single_write(fe, FSM_GO, 0x01);
+ udelay(250);
} 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, 0x5F, 0x13);
- 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);
+ /* 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);
+ 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, 0x5F, 0x13);
+ 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;
}
@@ -321,8 +300,10 @@ static int zl10353_init(struct dvb_front
static int zl10353_init(struct dvb_frontend *fe)
{
struct zl10353_state *state = fe->demodulator_priv;
- u8 zl10353_reset_attach[6] = { 0x50, 0x03, 0x64, 0x46, 0x15, 0x0F };
+ u8 zl10353_reset_attach[7] = { CONFIG, 0x03, 0x44, 0x46, 0x15, 0x0f, 0x80 };
+// u8 zl10353_unknown[] = { 0x90, 0x00, 0xff, 0xff, 0x00, 0xff, 0x3f, 0x3f };
int rc = 0;
+ u8 val;
#if 1
if (debug_regs)
@@ -332,7 +313,7 @@ static int zl10353_init(struct dvb_front
zl10353_reset_attach[2] &= ~0x20;
/* Do a "hard" reset if not already done */
- if (zl10353_read_register(state, 0x50) != zl10353_reset_attach[1] ||
+ if (zl10353_read_register(state, CONFIG) != zl10353_reset_attach[1] ||
zl10353_read_register(state, 0x51) != zl10353_reset_attach[2]) {
rc = zl10353_write(fe, zl10353_reset_attach,
sizeof(zl10353_reset_attach));
@@ -340,7 +321,29 @@ static int zl10353_init(struct dvb_front
if (debug_regs)
zl10353_dump_regs(fe);
#endif
- }
+ /* calibrate */
+ udelay(200);
+ zl10353_single_write(fe, 0xea , 0x01);
+ udelay(200);
+ zl10353_single_write(fe, 0xea , 0x00);
+
+ /* AGC2 */
+ val = 0x48;
+ if (state->config.agc2)
+ val &= ~0x40; /* clear bit 6 */
+ zl10353_single_write(fe, OP_CTL_0, val);
+
+ return state->config.demod_init(fe);
+ }
+
+
+#if 0
+ /* MSI Megasky 580 gl861 & Sigmatek DVB-110 au6610 does this */
+ if (state->config.unknown_init) {
+ zl10353_single_write(fe, 0x8e , 0x00);
+ rc = zl10353_write(fe, zl10353_unknown, sizeof(zl10353_unknown));
+ }
+#endif
return 0;
}
@@ -352,7 +355,7 @@ static int zl10353_i2c_gate_ctrl(struct
if (enable)
val |= 0x10;
- return zl10353_single_write(fe, 0x62, val);
+ return zl10353_single_write(fe, SCAN_CTL, val);
}
static void zl10353_release(struct dvb_frontend *fe)
diff -r 496bf62d9e03 linux/drivers/media/dvb/frontends/zl10353.h
--- a/linux/drivers/media/dvb/frontends/zl10353.h Thu Nov 15 12:07:19 2007 -0200
+++ b/linux/drivers/media/dvb/frontends/zl10353.h Thu Nov 15 17:02:19 2007 +0200
@@ -29,14 +29,23 @@ struct zl10353_config
/* demodulator's I2C address */
u8 demod_address;
- /* frequencies in kHz */
- int adc_clock; // default: 22528
+ /* demodulator's input clock */
+ int adc_clock; /* defaults to 20480 kHz */
/* set if no pll is connected to the secondary i2c bus */
int no_tuner;
/* set if parallel ts output is required */
int parallel_ts;
+
+ /* set if AGC2 is used */
+ u8 agc2;
+
+ /* extra init needed some devices */
+// u8 unknown_init;
+
+ /* Initialise the demodulator and PLL. Cannot be NULL */
+ int (*demod_init)(struct dvb_frontend* fe);
};
#if defined(CONFIG_DVB_ZL10353) || (defined(CONFIG_DVB_ZL10353_MODULE) && defined(MODULE))
@@ -51,4 +60,11 @@ static inline struct dvb_frontend* zl103
}
#endif // CONFIG_DVB_ZL10353
+static inline int zl10353_write_(struct dvb_frontend *fe, u8 *buf, int len) {
+ int r = 0;
+ if (fe->ops.write)
+ r = fe->ops.write(fe, buf, len);
+ return r;
+}
+
#endif /* ZL10353_H */
diff -r 496bf62d9e03 linux/drivers/media/dvb/frontends/zl10353_priv.h
--- a/linux/drivers/media/dvb/frontends/zl10353_priv.h Thu Nov 15 12:07:19 2007 -0200
+++ b/linux/drivers/media/dvb/frontends/zl10353_priv.h Thu Nov 15 17:02:19 2007 +0200
@@ -46,8 +46,14 @@ enum zl10353_reg_addr {
RS_ERR_CNT_0 = 0x13,
RS_UBC_1 = 0x14,
RS_UBC_0 = 0x15,
+ CONFIG = 0x50,
+ OP_CTL_0 = 0x5a,
+ SCAN_CTL = 0x62,
+ BW_CTL = 0x64,
TRL_NOMINAL_RATE_1 = 0x65,
TRL_NOMINAL_RATE_0 = 0x66,
+ TUNER_GO = 0x70,
+ FSM_GO = 0x71,
CHIP_ID = 0x7F,
};
_______________________________________________
linux-dvb mailing list
linux-dvb@xxxxxxxxxxx
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb