Mailing List archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[linux-dvb] grundig 29504-401 reload patch
Hi, here's a patch (for dvb-kernel) that allows this tuner module to be
reloaded. There's no good way to detect the thing if it has been powered
down, so the code is larger than I had hoped to be as safe as possible.
diff -Naur dvb-kernel.ORIGINAL/linux/drivers/media/dvb/frontends/grundig_29504-401.c dvb-kernel/linux/drivers/media/dvb/frontends/grundig_29504-401.c
--- dvb-kernel.ORIGINAL/linux/drivers/media/dvb/frontends/grundig_29504-401.c 2002-12-29 22:15:54.000000000 +0000
+++ dvb-kernel/linux/drivers/media/dvb/frontends/grundig_29504-401.c 2003-01-07 13:13:17.000000000 +0000
@@ -266,12 +266,16 @@
static
-void reset_and_configure (struct dvb_i2c_bus *i2c)
+int reset_and_configure (struct dvb_i2c_bus *i2c)
{
- u8 buf [] = { 0x06 };
- struct i2c_msg msg = { addr: 0x00, flags: 0, buf: buf, len: 1 };
+ u8 b1 [] = { 0x06 };
+ struct i2c_msg msg = { addr: 0x00, flags: 0, buf: b1, len: 1 };
- i2c->xfer (i2c, &msg, 1);
+ if (i2c->xfer(i2c, &msg, 1) != 1) {
+ return -1;
+ }
+
+ return 0;
}
@@ -401,7 +405,7 @@
case FE_SLEEP:
/* Power down */
- return l64781_writereg (i2c, 0x3e, 0x5a);
+ return l64781_writereg (i2c, 0x3e, 0x5a);
case FE_INIT:
return init (i2c);
@@ -418,24 +422,74 @@
static
int l64781_attach (struct dvb_i2c_bus *i2c)
{
- u8 b0 [] = { 0x1a };
+ u8 b0 [] = { 0x1a, 0 };
u8 b1 [] = { 0x00 };
- struct i2c_msg msg [] = { { addr: 0x55, flags: 0, buf: b0, len: 1 },
- { addr: 0x55, flags: I2C_M_RD, buf: b1, len: 1 } };
+ struct i2c_msg read_msg [] = { { addr: 0x55, flags: 0, buf: b0, len: 1 },
+ { addr: 0x55, flags: I2C_M_RD, buf: b1, len: 1 } };
+ struct i2c_msg write_msg [] = { { addr: 0x55, flags: 0, buf: b0, len: 2 } };
+ int tmp;
+ int i;
+
+ // OK, try and read byte 0x1a from the device. If this fails, this means
+ // either (a) the device is not present, or (b) the device is present, but
+ // not configured yet. In either case, we can skip the more in-depth tests
+ b0[0] = 0x1a;
+ if (i2c->xfer(i2c, read_msg, 2) == 2) {
+ // if nothing responds, device is not present
+ if (reset_and_configure(i2c))
+ return -ENODEV;
+
+ // read in 0x3e bytes from the device and OR their values together.
+ // If any read fails, a grundig device is not present
+ tmp = 0;
+ for(i = 0; i< 0x3e; i++) {
+ b0[0] = i;
+ if (i2c->xfer(i2c, read_msg, 2) != 2) {
+ return -ENODEV;
+ }
+ tmp |= b1[0];
+ }
+
+ // if the result was 0 (i.e. all memory locations were 0), it is likely
+ // we have a powered-down grundig chip. Power it up
+ if (tmp == 0) {
+ dprintk("Found potential powered-down grundig.\n");
+ b0[0] = 0x3e;
+ b0[1] = 0xa5;
+ if (i2c->xfer(i2c, write_msg, 1) != 1) {
+ return -ENODEV;
+ }
+ } else {
+ dprintk("Found potential powered-up grundig or eeprom.\n");
+ }
+ } else {
+ dprintk("Found unconfigured grundig or no device.\n");
+ }
- if (i2c->xfer (i2c, msg, 2) == 2) /* probably an EEPROM... */
- return -ENODEV;
+ if (reset_and_configure (i2c))
+ return -ENODEV;
- reset_and_configure (i2c);
+ b0[0] = 0x1a;
+ if (i2c->xfer (i2c, read_msg, 2) != 2)
+ return -ENODEV;
+ if (b1[0] != 0xa1)
+ return -ENODEV;
- if (i2c->xfer (i2c, msg, 2) != 2) /* nothing... */
+ b0[0] = 0x24;
+ if (i2c->xfer (i2c, read_msg, 2) != 2)
+ return -ENODEV;
+ if ((b1[0] & 0x3f) != 0x25)
return -ENODEV;
- if (b1[0] != 0xa1)
+ b0[0] = 0x25;
+ if (i2c->xfer (i2c, read_msg, 2) != 2)
+ return -ENODEV;
+ if ((b1[0] & 0x3f) != 0x2c)
return -ENODEV;
dvb_register_frontend (grundig_29504_401_ioctl, i2c, NULL,
&grundig_29504_401_info);
+
return 0;
}
Home |
Main Index |
Thread Index