Robert Schlabbach wrote:

The odd/even trick makes the SAA7146A automatically switch between two
buffers. The ugly side of this is that you have to busy-wait for it to
really switch buffers and then _copy_ the data out of the DMA buffer.

Yep, I tried doing a busy wait before I came up with the solution to infer the pointer position from the olddma pointer. I did a patch which catches the suspect pointer and just busy waits until it has moved to a different location. It often takes several microseconds for the DMA pointer to make up its mind.


I have attached the patch against the dvb-kernel code for reference in case anyone wants to try it out. I don't recommend it since it doesn't appear to work any better than the solution I posted earlier and it consumes a few more CPU cycles doing the busy waits.

Jon

diff -urw cvs/dvb-kernel/linux/drivers/media/dvb/ttpci/budget-core.c 
dvb-kernel/linux/drivers/media/dvb/ttpci/budget-core.c
--- cvs/dvb-kernel/linux/drivers/media/dvb/ttpci/budget-core.c  2003-06-26 
18:42:36.000000000 +0100
+++ dvb-kernel/linux/drivers/media/dvb/ttpci/budget-core.c      2003-08-30 
01:25:11.000000000 +0100
@@ -68,6 +68,18 @@
         u32 olddma = budget->ttbp;
         u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
 
+#define MAX_COUNT 100
+       int count = MAX_COUNT;
+       while ((( newdma == 0) || (newdma == TS_BUFLEN / 2)) && (count != 0)){
+         /* DMA pointer looks suspect */
+         udelay(1);
+         newdma = saa7146_read(budget->dev, PCI_VDP3);
+         count--;
+       }
+       if (count < (MAX_COUNT/2)) {
+         ERR(("DMA stuck for %dus\n", MAX_COUNT - count));
+       }
+
         /* nearest lower position divisible by 188 */
         newdma -= newdma % 188;
 

Reply via email to