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