On Mon, 2008-05-12 at 16:55 -0700, Michael wrote:

> > > > The "Invalid EEPROM" message and "Could not start the CPU" are of
> > > > interest, but we need to see all the log messages, since cx18 relies on
> > > > and loads tveeprom, cs5345, mxl5005s, cx25840, tuner, and other modules.
> > > > The grep cuts out their messages.
> > > > 
> > > > Also could you do:
> > > > 
> > > > # modprobe -r cx18
> > > > # modprobe tveeprom debug=1
> > > > # modprobe cx18 debug=71
> > > > 
> > > >
> > > > To enable tveeprom debug messages and cx18 info, warn, mailbox, and i2c
> > > > messages.
> > > 
> > > 
> > > And heres the dmesg from this:
> > > 
> > > cx18:  Start initialization, version 1.0.0
> > > tveeprom 0-0050: full 256-byte eeprom dump:
> > > tveeprom 0-0050: 00: 00 70 00 44 74 00 00 00 84 09 00 04 20 77 00 40
> > > tveeprom 0-0050: 10: 3c 6e 2d f0 73 05 26 00 84 08 00 06 2d 23 01 00
> > > tveeprom 0-0050: 20: 96 58 8d 72 07 70 73 09 1f 36 73 0a 08 74 73 0b
> > > tveeprom 0-0050: 30: 4f 30 72 0e 01 72 10 01 72 11 00 79 25 00 00 00
> > > tveeprom 0-0050: 40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> > > tveeprom 0-0050: 50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> > > tveeprom 0-0050: 60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> > > tveeprom 0-0050: 70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> > > tveeprom 0-0050: 80: 00 00 00 00 84 09 00 04 20 77 00 40 3c 6e 2d f0
> > > tveeprom 0-0050: 90: 73 05 26 00 84 08 00 06 2d 23 01 00 96 58 8d 72
> > > tveeprom 0-0050: a0: 07 70 73 09 1f 36 73 0a 08 74 73 0b 4f 30 72 0e
> > > tveeprom 0-0050: b0: 01 72 10 01 72 11 00 79 25 00 00 00 00 00 00 00
> > > tveeprom 0-0050: c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> > > tveeprom 0-0050: d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> > > tveeprom 0-0050: e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> > > tveeprom 0-0050: f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> > > tveeprom 0-0050: Tag [04] + 8 bytes: 20 77 00 40 3c 6e 2d f0
> > > tveeprom 0-0050: Tag [05] + 2 bytes: 26 00
> > > tveeprom 0-0050: Tag [06] + 7 bytes: 2d 23 01 00 96 58 8d
> > > tveeprom 0-0050: Tag [07] + 1 bytes: 70
> > > tveeprom 0-0050: Tag [09] + 2 bytes: 1f 36
> > > tveeprom 0-0050: Tag [0a] + 2 bytes: 08 74
> > > tveeprom 0-0050: Tag [0b] + 2 bytes: 4f 30
> > > tveeprom 0-0050: Tag [0e] + 1 bytes: 01
> > > tveeprom 0-0050: Tag [10] + 1 bytes: 01
> > > tveeprom 0-0050: Not sure what to do with tag [10]
> > > tveeprom 0-0050: Tag [11] + 1 bytes: 00
> > > tveeprom 0-0050: Not sure what to do with tag [11]
> > > tveeprom 0-0050: Hauppauge model 74541, rev C5B6, serial# 2977340
> > > tveeprom 0-0050: MAC address is 00-0D-FE-2D-6E-3C
> > > tveeprom 0-0050: tuner model is Philips FM1236 MK5 (idx 116, type 43)
> > > tveeprom 0-0050: TV standards NTSC(M) (eeprom 0x08)
> > > tveeprom 0-0050: audio processor is CX23418 (idx 38)
> > > tveeprom 0-0050: decoder processor is CX23418 (idx 31)
> > > tveeprom 0-0050: has radio, has no IR receiver, has no IR transmitter
> > > cx18-0: Unknown model 74541, defaulting to HVR-1600
> > > cx18-0: Autodetected Hauppauge HVR-1600
> > 
> > Here's something odd.  In all your previous load attempts, the EEPROM
> > wasn't recognized as valid, and that was a problem.  On this particular
> > load attempt, the EEPROM was read properly.  As you continue to try and
> > get this driver working, keep an eye on this.
> > 
> > One thing to look for is as to whether or not the pre-loading tveeprom
> > module make the difference or setting the debug option for the tveeprom
> > module makes the difference (on the command line and
> > in /etc/modporbe.conf).
> > 
> > Another thing to look for is how busy was the I/O system at the time you
> > loaded the module as to whether the EEPROM is read properly (if there's
> > lots of disk, graphics, or network I/O going on when you load the
> > driver).
> > 
> > I was suspecting you had the i2c problems other users are having, but
> > this time the EEPROM read worked, so I don't know.
> > 
> > 
> dmesg:
> 
> cx18:  Start initialization, version 1.0.0
> cx18-0: Initializing card #0
> cx18-0: Autodetected Hauppauge card
> cx18-0 info: base addr: 0xf4000000
> cx18-0 info: Enabling pci device
> cx18-0 info: cx23418 (rev 0) at 02:02.0, irq: 17, latency: 64, memory: 
> 0xf4000000
> cx18-0 info: attempting ioremap at 0xf4000000 len 0x04000000
> cx18-0: cx23418 revision 01010000 (B)
> cx18-0 info: GPIO initial dir: 0000ffff out: 00000000
> cx18-0 info: activating i2c...
> cx18-0 i2c: i2c init
> cx18-0 info: Active card count: 1.
> tveeprom 0-0050: Encountered bad packet header [00]. Corrupt or not a 
> Hauppauge eeprom.
> cx18-0: Invalid EEPROM
> cx18-0: DVB & VBI are not yet supported
> cx18-0 info: Loaded module tuner
> cx18-0 info: Loaded module cs5345
> cx18-0 i2c: i2c client register
> cx18-0 i2c: i2c client register
> cs5345 0-004c: chip found @ 0x98 (cx18 i2c driver #0-0)
> cx18-0 info: Allocate encoder MPEG stream: 63 x 32768 buffers (2016kB total)
> cx18-0 info: Allocate TS stream: 32 x 32768 buffers (1024kB total)
> cx18-0 info: Allocate encoder YUV stream: 16 x 131072 buffers (2048kB total)
> cx18-0 info: Allocate encoder PCM audio stream: 63 x 16384 buffers (1008kB 
> total)
> cx18-0: Disabled encoder IDX device
> videodev: "" has no release callback. Please fix your driver for proper sysfs 
> support, see http://lwn.net/Articles/36850/
> cx18-0: Registered device video0 for encoder MPEG (2 MB)
> DVB: registering new adapter (cx18).
> MXL5005S: Attached at address 0x63
> DVB: registering frontend 0 (Samsung S5H1409 QAM/8VSB Frontend)...
> cx18-0: DVB Frontend registered
> videodev: "" has no release callback. Please fix your driver for proper sysfs 
> support, see http://lwn.net/Articles/36850/
> cx18-0: Registered device video32 for encoder YUV (2 MB)
> videodev: "" has no release callback. Please fix your driver for proper sysfs 
> support, see http://lwn.net/Articles/36850/
> cx18-0: Registered device video24 for encoder PCM audio (1 MB)
> videodev: "" has no release callback. Please fix your driver for proper sysfs 
> support, see http://lwn.net/Articles/36850/
> cx18-0: Registered device radio-64 for encoder radio
> cx18-0 info: load segment a00000-a07fff
> cx18-0 info: load segment ae0000-ae00ff
> cx18-0 info: load segment b00000-b1a65f
> cx18-0: loaded v4l-cx23418-apu.fw firmware V00120000 (141200 bytes)
> cx18-0: loaded v4l-cx23418-cpu.fw firmware (174716 bytes)
> cx18-0 info: load segment a00000-a07fff
> cx18-0 info: load segment ae0000-ae00ff
> cx18-0 info: load segment b00000-b1a65f
> cx18-0 info: Changing input from 1 to 0
> cx18-0 info: Mute
> cx18-0 info: cmd 4008646f triggered fw load
> cx18-0: loaded v4l-cx23418-dig.fw firmware (16382 bytes)
> cx18-0 info: decoder set video input 7, audio input 8
> cx18-0 i2c: call_i2c_client addr=4c
> cx18-0 info: decoder set video input 7, audio input 8
> cx18-0 info: Unmute
> cx18-0 info: Switching standard to 1000.
> cx18-0 info: changing video std to fmt 1
> cx18-0 info: PLL regs = int: 15, frac: 2876158, post: 4
> cx18-0 info: PLL = 0.000011 MHz
> cx18-0 info: PLL/8 = 0.000001 MHz
> cx18-0 info: ADC Sampling freq = 0.000001 MHz
> cx18-0 info: Chroma sub-carrier freq = 0.000000 MHz
> cx18-0 info: hblank 122, hactive 720, vblank 26 , vactive 487, vblank656 26, 
> src_dec 543,burst 0x5b, luma_lpf 1, uv_lpf 1, comb 0x66, sc 0x087c1f
> cx18-0 info: Mute
> cx18-0 info: v4l2 ioctl: set frequency 1076
> cx18-0 info: Unmute
> cx18-0: Initialized card #0: Hauppauge HVR-1600
> cx18:  End initialization
> 
> 
> Once again though, I only see it once.

Hmmm.  I'm not sure why the firmware load doesn't happen twice.  I'm
working under the assumption you're using the latest driver from :
http://www.linuxtv.org/hg/v4l-dvb

What I think I can help with, or more accurately you can help me with is
investigating your intermittent EEPROM error.  The attached patch
enables adds a lot of debugging to gain some insight into what's going
on with the i2c bus while the operations like reading the EEPROM are
taking place.  I also have some other code in there to try to recover
from any PCI bus induced i2c errors if they occur.

If you'd like to help, here's how to test the patch:

$ cd (path-to-source-code)/v4l-dvb
$ patch -p1 < (path-to-patch)/cx18-i2c-debugging2.patch
$ make
$ su - root
# cd (path-to-source-code)/v4l-dvb
# make unload
# make install
# logger START TEST 1
# modprobe cx18 debug=323
# logger END TEST 1

Then look in /var/log/messages for the lines between "START TEST 1" and
"END TEST 1", dmesg will have filled up and wrpped around with the
amount of messages written.


On my working system, I get something like this:

May 12 21:34:37 palomino andy: START TEST 2
May 12 21:34:45 palomino kernel: cx18:  Start initialization, version 1.0.0
May 12 21:34:45 palomino kernel: cx18-0: Initializing card #0
May 12 21:34:45 palomino kernel: cx18-0: Autodetected Hauppauge card
May 12 21:34:45 palomino kernel: cx18-0 info: base addr: 0xf4000000
May 12 21:34:45 palomino kernel: cx18-0 info: Enabling pci device
May 12 21:34:45 palomino kernel: ACPI: PCI Interrupt 0000:02:01.0[A] -> GSI 21 
(level, low) -> IRQ 21
May 12 21:34:45 palomino kernel: cx18-0 info: cx23418 (rev 0) at 02:01.0, irq: 
21, latency: 64, memory: 0xf4000000
May 12 21:34:45 palomino kernel: cx18-0 info: attempting ioremap at 0xf4000000 
len 0x04000000
May 12 21:34:45 palomino kernel: cx18-0: cx23418 revision 01010000 (B)
May 12 21:34:45 palomino kernel: cx18-0 info: GPIO initial dir: 0000cffe out: 
00003001
May 12 21:34:45 palomino kernel: cx18-0 info: activating i2c...
May 12 21:34:45 palomino kernel: cx18-0 i2c: i2c init
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_setscl: On entry 
CX18_REG_I2C_1_WR = 0x21c0b
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_setscl: Wrote    
CX18_REG_I2C_1_WR = 0x21c0b
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_setscl: Readback 
CX18_REG_I2C_1_WR = 0x21c0b
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_setsda: On entry 
CX18_REG_I2C_1_WR = 0x21c0b
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_setsda: Wrote    
CX18_REG_I2C_1_WR = 0x21c0b
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_setsda: Readback 
CX18_REG_I2C_1_WR = 0x21c0b
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_setscl: On entry 
CX18_REG_I2C_2_WR = 0x21c0b
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_setscl: Wrote    
CX18_REG_I2C_2_WR = 0x21c0b
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_setscl: Readback 
CX18_REG_I2C_2_WR = 0x21c0b
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_setsda: On entry 
CX18_REG_I2C_2_WR = 0x21c0b
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_setsda: Wrote    
CX18_REG_I2C_2_WR = 0x21c0b
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_setsda: Readback 
CX18_REG_I2C_2_WR = 0x21c0b
May 12 21:34:45 palomino kernel: cx18-0 info: Active card count: 1.
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_setsda: On entry 
CX18_REG_I2C_1_WR = 0x21c0b
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_setsda: Wrote    
CX18_REG_I2C_1_WR = 0x21c09
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_setsda: Readback 
CX18_REG_I2C_1_WR = 0x21c09
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_setscl: On entry 
CX18_REG_I2C_1_WR = 0x21c09
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_setscl: Wrote    
CX18_REG_I2C_1_WR = 0x21c08
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_setscl: Readback 
CX18_REG_I2C_1_WR = 0x21c08
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_setsda: On entry 
CX18_REG_I2C_1_WR = 0x21c08
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_setsda: Wrote    
CX18_REG_I2C_1_WR = 0x21c0a
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_setsda: Readback 
CX18_REG_I2C_1_WR = 0x21c0a
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_setscl: On entry 
CX18_REG_I2C_1_WR = 0x21c0a
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_setscl: Wrote    
CX18_REG_I2C_1_WR = 0x21c0b
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_setscl: Readback 
CX18_REG_I2C_1_WR = 0x21c0b
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_getscl: read CX18_REG_I2C_1_RD 
= 0xc
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_setscl: On entry 
CX18_REG_I2C_1_WR = 0x21c0b
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_setscl: Wrote    
CX18_REG_I2C_1_WR = 0x21c0a
May 12 21:34:45 palomino kernel: cx180 i2c: cx18_setscl: Readback 
CX18_REG_I2C_1_WR = 0x21c0a


If you see values that don't start out with 0x21c0? for the WR register
or values that are larger than 0xf for the RD register or any different
log messages coming from get/set_scl/sca(), then I'd be interested in
the output.


If you can't do this, that's OK.  I'll take some time to look at what
might be causing the firmware not to load twice and get back when I have
time.


Regards,
Andy







diff -r d87638488880 linux/drivers/media/video/cx18/cx18-driver.c
--- a/linux/drivers/media/video/cx18/cx18-driver.c	Thu May 01 03:23:23 2008 -0400
+++ b/linux/drivers/media/video/cx18/cx18-driver.c	Mon May 12 21:17:33 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));
@@ -355,6 +361,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 d87638488880 linux/drivers/media/video/cx18/cx18-driver.h
--- a/linux/drivers/media/video/cx18/cx18-driver.h	Thu May 01 03:23:23 2008 -0400
+++ b/linux/drivers/media/video/cx18/cx18-driver.h	Mon May 12 21:17:33 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 */
@@ -344,6 +345,7 @@ struct cx18_i2c_algo_callback_data {
 struct cx18_i2c_algo_callback_data {
 	struct cx18 *cx;
 	int bus_index;   /* 0 or 1 for the cx23418's 1st or 2nd I2C bus */
+	u32 wr_reg_copy; /* copy of last written to the cx23418's i2c ctl reg */
 };
 
 /* Struct to hold info about cx18 cards */
diff -r d87638488880 linux/drivers/media/video/cx18/cx18-i2c.c
--- a/linux/drivers/media/video/cx18/cx18-i2c.c	Thu May 01 03:23:23 2008 -0400
+++ b/linux/drivers/media/video/cx18/cx18-i2c.c	Mon May 12 21:17:33 2008 -0400
@@ -181,12 +181,43 @@ static void cx18_setscl(void *data, int 
 	struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
 	int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
 	u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;
+	u32 rprev = ((struct cx18_i2c_algo_callback_data *)data)->wr_reg_copy;
 	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 ((rprev & ~0xf) != (r & ~0xf)) {
+		CX18_DEBUG_WARN("cx18_setscl: On entry read value (%#0x) and "
+			"previously written value (%#0x) upper bytes differ." 
+			" Using previous value as it should be correct.\n",
+			r, rprev);
+		r = rprev;
+	}
+
 	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);
+	((struct cx18_i2c_algo_callback_data *)data)->wr_reg_copy = r;
+	CX18_DEBUG_HI_I2C("cx18_setscl: Wrote    CX18_REG_I2C_%d_WR = %#0x\n",
+			  bus_index+1, r);
+
+	rprev = 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);
+	if ((rprev & ~0xf) != (r & ~0xf)) {
+		CX18_DEBUG_WARN("cx18_setscl: On exit readback value (%#0x) and"
+			" written value (%#0x) upper bytes differ\n",
+			r, rprev);
+	}
+	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)
@@ -194,12 +225,43 @@ static void cx18_setsda(void *data, int 
 	struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
 	int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
 	u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;
+	u32 rprev = ((struct cx18_i2c_algo_callback_data *)data)->wr_reg_copy;
 	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 ((rprev & ~0xf) != (r & ~0xf)) {
+		CX18_DEBUG_WARN("cx18_setsda: On entry read value (%#0x) and "
+			"previously written value (%#0x) upper bytes differ." 
+			" Using previous value as it should be correct.\n",
+			r, rprev);
+		r = rprev;
+	}
+
 	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);
+	((struct cx18_i2c_algo_callback_data *)data)->wr_reg_copy = r;
+	CX18_DEBUG_HI_I2C("cx18_setsda: Wrote    CX18_REG_I2C_%d_WR = %#0x\n",
+			  bus_index+1, r);
+
+	rprev = 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);
+	if ((rprev & ~0xf) != (r & ~0xf)) {
+		CX18_DEBUG_WARN("cx18_setsda: On exit readback value (%#0x) and"
+			" written value (%#0x) upper bytes differ\n",
+			r, rprev);
+	}
+	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)
@@ -207,8 +269,17 @@ static int cx18_getscl(void *data)
 	struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
 	int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
 	u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD;
-
-	return read_reg(addr) & GETSCL_BIT;
+	u32 r;
+
+	for (r = read_reg(addr); r == 0xffffffff; r = read_reg(addr)) 
+		CX18_DEBUG_WARN("cx18_getscl CX18_REG_I2C_%d_RD returned "
+				"0xffffffff "
+				"possible aborted PCI bus read\n", bus_index+1);
+
+	CX18_DEBUG_HI_I2C("cx18_getscl: read CX18_REG_I2C_%d_RD = %#0x\n",
+			  bus_index+1, r);
+
+	return r & GETSCL_BIT;
 }
 
 static int cx18_getsda(void *data)
@@ -216,8 +287,17 @@ static int cx18_getsda(void *data)
 	struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
 	int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
 	u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD;
-
-	return read_reg(addr) & GETSDL_BIT;
+	u32 r;
+
+	for (r = read_reg(addr); r == 0xffffffff; r = read_reg(addr)) 
+		CX18_DEBUG_WARN("cx18_getsda CX18_REG_I2C_%d_RD returned "
+				"0xffffffff "
+				"possible aborted PCI bus read\n", bus_index+1);
+
+	CX18_DEBUG_HI_I2C("cx18_getsda: read CX18_REG_I2C_%d_RD = %#0x\n",
+			  bus_index+1, r);
+
+	return r & GETSDL_BIT;
 }
 
 /* template for i2c-bit-algo */
@@ -382,6 +462,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));
@@ -389,6 +470,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];
 
@@ -423,11 +505,13 @@ int init_cx18_i2c(struct cx18 *cx)
 
 	/* Hw I2C1 Clock Freq ~100kHz */
 	write_reg_sync(0x00021c0f & ~4, CX18_REG_I2C_1_WR);
+	cx->i2c_algo_cb_data[0].wr_reg_copy = 0x00021c0f & ~4;
 	cx18_setscl(&cx->i2c_algo_cb_data[0], 1);
 	cx18_setsda(&cx->i2c_algo_cb_data[0], 1);
 
 	/* Hw I2C2 Clock Freq ~100kHz */
 	write_reg_sync(0x00021c0f & ~4, CX18_REG_I2C_2_WR);
+	cx->i2c_algo_cb_data[1].wr_reg_copy = 0x00021c0f & ~4;
 	cx18_setscl(&cx->i2c_algo_cb_data[1], 1);
 	cx18_setsda(&cx->i2c_algo_cb_data[1], 1);
 
@@ -438,9 +522,17 @@ void exit_cx18_i2c(struct cx18 *cx)
 void exit_cx18_i2c(struct cx18 *cx)
 {
 	int i;
+	u32 r;
+
 	CX18_DEBUG_I2C("i2c exit\n");
-	write_reg(read_reg(CX18_REG_I2C_1_WR) | 4, CX18_REG_I2C_1_WR);
-	write_reg(read_reg(CX18_REG_I2C_2_WR) | 4, CX18_REG_I2C_2_WR);
+
+	r = read_reg(CX18_REG_I2C_1_WR);
+	write_reg(r | 4, CX18_REG_I2C_1_WR);
+	cx->i2c_algo_cb_data[0].wr_reg_copy = r | 4;
+
+	r = read_reg(CX18_REG_I2C_2_WR);
+	write_reg(r | 4, CX18_REG_I2C_2_WR);
+	cx->i2c_algo_cb_data[1].wr_reg_copy = r | 4;
 
 	for (i = 0; i < 2; i++) {
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
_______________________________________________
ivtv-users mailing list
[email protected]
http://ivtvdriver.org/mailman/listinfo/ivtv-users

Reply via email to