On Fri, 2008-04-25 at 23:36 -0400, Andy Walls wrote:
> On Fri, 2008-04-25 at 23:01 -0400, Andy Walls wrote:
> > Ryan Watts wrote:
> > 
> > >   I have attached
> > > the
> > > debug output from dmesg since it is too lengthy to put in an e-mail.  I am
> > > using
> > > a 2.6.22.9 kernel with i2c debug.  The output is after using "modprobe
> > > i2c_algo_bit
> > > i2c_debug=3" and "modprobe cx18 debug=511".
> > > 
> > > I have also attached the output from "lspci -tv", "lspci -vvvnnxxx", and
> > > "lsmod".
> > > 
> > > If you need anything else, let me know.  I have a logic analyzer that I 
> > > can
> > > hook up.
> > 
> > 
> > >   I was going to try and
> > > make
> > > a PCI breakout card (i thought the problem might be with the PCI bus) but 
> > > I
> > > don't
> > > have enough time and my logic analyzer only has 12 channels.
> > 
> > That's probably overkill for right now.  There are software indications
> > of PCI bus errors that supposedly the kernel can notify the driver
> > about.  I'm going to write a callback routine to try and catch any of
> > these.  
> > 
> > 
> > 
> > I'll look over you log outputs, 
> 
> 
> Woo hoo!  One more level of causality uncovered:
> 
> [ 1788.534047] Linux video capture interface: v2.00
> [ 1788.561795] cx18:  Start initialization, version 0.1.0
> [ 1788.562080] cx18-0: Initializing card #0
> [ 1788.562089] cx18-0: Autodetected Hauppauge card
> [ 1788.562096] cx18-0 info: base addr: 0xdc000000
> [ 1788.562098] cx18-0 info: Enabling pci device
> [ 1788.562117] cx18-0 info: cx23418 (rev 0) at 00:0d.0, irq: 17, latency: 64, 
> memory: 0xdc000000
> [ 1788.562122] cx18-0 info: attempting ioremap at 0xdc000000 len 0x04000000
> [ 1788.563025] cx18-0: cx23418 revision 01010000 (B)
> [ 1788.636892] cx18-0 info: GPIO initial dir: 0000ffff out: 00000000
> [ 1788.636921] cx18-0 info: activating i2c...
> [ 1788.636924] cx18-0 i2c: i2c init
> [ 1788.659560] cx18-0 warning: setscl failed to write to CX18_REG_I2C_1_WR 
> register to drive bus 1 SCL line to 0
> [ 1788.659906] cx18-0 warning: setscl failed to write to CX18_REG_I2C_1_WR 
> register to drive bus 1 SCL line to 0
> [ 1788.660246] cx18-0 warning: setscl failed to write to CX18_REG_I2C_1_WR 
> register to drive bus 1 SCL line to 0
> [...]
> 
> The CPU is writing out, over the PCI bus, a value to a cx23418 control
> register for the I2C bus lines.  The readback doesn't match what was
> written!

> The messages above show failure for times (maybe not all) your CPU tries
> to have the CX23418 pull an I2C line low.
> 
> There are three high level reasons why this could be:
> 1. Bona-fide PCI bus problems, such that the writes don't complete or
> actual bus errors.
> 2. Setup of the I2C hardware block in the cx23418 failed and it's not
> accepting commands in those registers
> 3. The command is actually going to the CX23418, but host bridge is
> sending us back an old/cached value on readback.
> 
> 
> I'll have to think about tests to run still.  I'll get back to you
> tomorrow.

Ryan,

1. Please get the latest driver at:

http://linuxtv.org/hg/~hverkuil/v4l-dvb-cx18/archive/tip.tar.bz2

2. Apply the attached patch.  It only adds two things: verbose reporting
in cx18_setsdl() and cx18_setsda(); and a module parameter to vary the
I2C SCL clock period we tell i2c-algo-bit to use.

3. Build and install the patched driver

4. Do a

# modprobe cx18 debug=321 i2c_clock_period=10

to make sure it behaves "normally" per your past experience.


5. Then try

# modprobe -r cx18
# modprobe cx18 debug=321 i2c_clock_period=4000

The driver will take longer to install and you may notice CPU
utilization increases due to busy waits in i2c-algo-bit.ko; don't worry
about that for now.

(If the driver takes *forever* to load, we've set the clock too slow for
your machine.  Delete the cx18.ko file from under /lib/modules/... ,
"sync" the disks and reboot the machine.)

Check to see if the driver actually detects the EEPROM properly with the
slower I2C clock.

6.  Shutdown and reboot into single user mode.

7. Stop as many unnecessary services as you can (you probably need to
keep syslog and udev running though) and modprobe -r as many modules as
you can and still have the mouse, keyboard, text video, and disks
working.

8. Repeat steps 5 & 6 above to see if the driver can read the EEPROM
properly now.



Some versions of your motherboards VIA chipset has a bit of a
reputation.  See the readme's for George Breese's windows utilities:

http://www.georgebreese.com/net/software/#PCI

and also in the kernel source:

linux/drivers/pci/quirks.c:


> /*
>  *      VIA Apollo KT133 needs PCI latency patch
>  *      Made according to a windows driver based patch by George E. Breese
>  *      see PCI Latency Adjust on 
> http://www.viahardware.com/download/viatweak.shtm
>  *      Also see http://www.au-ja.org/review-kt133a-1-en.phtml for
>  *      the info on which Mr Breese based his work.
>  *
>  *      Updated based on further information from the site and also on
>  *      information provided by VIA 
>  */
> static void quirk_vialatency(struct pci_dev *dev)
> {
[...]
>         /*
>          *      Ok we have the problem. Now set the PCI master grant to 
>          *      occur every master grant. The apparent bug is that under high
>          *      PCI load (quite common in Linux of course) you can get data
>          *      loss when the CPU is held off the bus for 3 bus master 
> requests
>          *      This happens to include the IDE controllers....
>          *
>          *      VIA only apply this fix when an SB Live! is present but under
>          *      both Linux and Windows this isnt enough, and we have seen
>          *      corruption without SB Live! but with things like 3 UDMA IDE
>          *      controllers. So we ignore that bit of the VIA recommendation..
>          */

I need to check the logs you sent to see if you have an affected version
of the chipset.  (BTW could you run the lspci commands again as root, it
makes a difference.)

Also, writing an PCI error handler callback is not useful for most
architectures expcept for ppc, for non-PCI cards.  So it may come down
to watching some signals on the PCI bus, or writing some software to
check on some VIA chipset specific features to detect bus errors.


Regards,
Andy 



diff -r 9377f0ecba44 linux/drivers/media/video/cx18/cx18-driver.c
--- a/linux/drivers/media/video/cx18/cx18-driver.c	Mon Apr 28 22:27:08 2008 +0200
+++ b/linux/drivers/media/video/cx18/cx18-driver.c	Mon Apr 28 21:32:05 2008 -0400
@@ -89,6 +89,7 @@ static int enc_pcm_buffers = CX18_DEFAUL
 static int enc_pcm_buffers = CX18_DEFAULT_ENC_PCM_BUFFERS;
 
 static int cx18_pci_latency = 1;
+static int i2c_clock_period = 10;
 
 int cx18_debug;
 
@@ -100,6 +101,7 @@ module_param_string(ntsc, ntsc, sizeof(n
 module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
 module_param_named(debug, cx18_debug, int, 0644);
 module_param(cx18_pci_latency, int, 0644);
+module_param(i2c_clock_period, int, 0644);
 module_param(cx18_first_minor, int, 0644);
 
 module_param(enc_mpg_buffers, int, 0644);
@@ -139,6 +141,10 @@ MODULE_PARM_DESC(cx18_pci_latency,
 MODULE_PARM_DESC(cx18_pci_latency,
 		 "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n"
 		 "\t\t\tDefault: Yes");
+MODULE_PARM_DESC(i2c_clock_period,
+		 "Period of SCL for I2C buses controlled by CX23418 (in usecs)\n"
+		 "\t\t\tMinimum: 10 usec (100 kHz), Maximum: 4500 usec (222 Hz)\n"
+		 "\t\t\tDefault: 10 usec");
 MODULE_PARM_DESC(enc_mpg_buffers,
 		 "Encoder MPG Buffers (in MB)\n"
 		 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFFERS));
@@ -365,6 +371,13 @@ static void cx18_process_options(struct 
 	cx->options.tuner = tuner[cx->num];
 	cx->options.radio = radio[cx->num];
 
+	if (i2c_clock_period < 10)
+		cx->options.i2c_clock_period = 10;
+	else if (i2c_clock_period > 4500)
+		cx->options.i2c_clock_period = 4500;
+	else
+		cx->options.i2c_clock_period = i2c_clock_period;
+
 	cx->std = cx18_parse_std(cx);
 	if (cx->options.cardtype == -1) {
 		CX18_INFO("Ignore card\n");
diff -r 9377f0ecba44 linux/drivers/media/video/cx18/cx18-driver.h
--- a/linux/drivers/media/video/cx18/cx18-driver.h	Mon Apr 28 22:27:08 2008 +0200
+++ b/linux/drivers/media/video/cx18/cx18-driver.h	Mon Apr 28 21:32:05 2008 -0400
@@ -176,6 +176,7 @@ struct cx18_options {
 	int cardtype;		/* force card type on load */
 	int tuner;		/* set tuner on load */
 	int radio;		/* enable/disable radio */
+	int i2c_clock_period;	/* period of SCL for I2C buses */
 };
 
 /* per-buffer bit flags */
diff -r 9377f0ecba44 linux/drivers/media/video/cx18/cx18-i2c.c
--- a/linux/drivers/media/video/cx18/cx18-i2c.c	Mon Apr 28 22:27:08 2008 +0200
+++ b/linux/drivers/media/video/cx18/cx18-i2c.c	Mon Apr 28 21:32:05 2008 -0400
@@ -182,10 +182,23 @@ static void cx18_setscl(void *data, int 
 	u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;
 	u32 r = read_reg(addr);
 
+	CX18_DEBUG_HI_I2C("cx18_setscl: On entry CX18_REG_I2C_%d_WR = %#0x\n",
+			  bus_index+1, r);
 	if (state)
-		write_reg_sync(r | SETSCL_BIT, addr);
+		r |= SETSCL_BIT;
 	else
-		write_reg_sync(r & ~SETSCL_BIT, addr);
+		r &= ~SETSCL_BIT;
+	write_reg(r, addr);
+	CX18_DEBUG_HI_I2C("cx18_setscl: Wrote    CX18_REG_I2C_%d_WR = %#0x\n",
+			  bus_index+1, r);
+	r = read_reg(addr); /* Flush potentially posted write */
+	CX18_DEBUG_HI_I2C("cx18_setscl: Readback CX18_REG_I2C_%d_WR = %#0x\n",
+			  bus_index+1, r);
+	r &= SETSCL_BIT;
+	if ((state && !r) || (!state && r))
+		CX18_DEBUG_WARN("setscl failed to write to CX18_REG_I2C_%d_WR "
+				"register to drive bus %d SCL line to %d\n",
+				bus_index+1, bus_index+1, state);
 }
 
 static void cx18_setsda(void *data, int state)
@@ -195,10 +208,23 @@ static void cx18_setsda(void *data, int 
 	u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;
 	u32 r = read_reg(addr);
 
+	CX18_DEBUG_HI_I2C("cx18_setsda: On entry CX18_REG_I2C_%d_WR = %#0x\n",
+			  bus_index+1, r);
 	if (state)
-		write_reg_sync(r | SETSDL_BIT, addr);
+		r |= SETSDL_BIT;
 	else
-		write_reg_sync(r & ~SETSDL_BIT, addr);
+		r &= ~SETSDL_BIT;
+	write_reg(r, addr);
+	CX18_DEBUG_HI_I2C("cx18_setsda: Wrote    CX18_REG_I2C_%d_WR = %#0x\n",
+			  bus_index+1, r);
+	r = read_reg(addr); /* Flush potentially posted write */
+	CX18_DEBUG_HI_I2C("cx18_setsda: Readback CX18_REG_I2C_%d_WR = %#0x\n",
+			  bus_index+1, r);
+	r &= SETSDL_BIT;
+	if ((state && !r) || (!state && r))
+		CX18_DEBUG_WARN("setsda failed to write to CX18_REG_I2C_%d_WR "
+				"register to drive bus %d SDA line to %d\n",
+				bus_index+1, bus_index+1, state);
 }
 
 static int cx18_getscl(void *data)
@@ -381,6 +407,7 @@ int init_cx18_i2c(struct cx18 *cx)
 	int i;
 	CX18_DEBUG_I2C("i2c init\n");
 
+
 	for (i = 0; i < 2; i++) {
 		memcpy(&cx->i2c_adap[i], &cx18_i2c_adap_template,
 			sizeof(struct i2c_adapter));
@@ -388,6 +415,7 @@ int init_cx18_i2c(struct cx18 *cx)
 			sizeof(struct i2c_algo_bit_data));
 		cx->i2c_algo_cb_data[i].cx = cx;
 		cx->i2c_algo_cb_data[i].bus_index = i;
+		cx->i2c_algo[i].udelay = cx->options.i2c_clock_period/2;
 		cx->i2c_algo[i].data = &cx->i2c_algo_cb_data[i];
 		cx->i2c_adap[i].algo_data = &cx->i2c_algo[i];
 
_______________________________________________
ivtv-devel mailing list
[email protected]
http://ivtvdriver.org/mailman/listinfo/ivtv-devel

Reply via email to