I found the problem with DMA on the ARM architecture - actually it's a problem
with DMA in general but it doesn't affect the x86 architecture so its never
been noticed.
The fix requires some endian patches which Hans committed already to r3741 in
svn-trunk. The other fixes are in the attached patch. These should be applied
to the driver directory and should not have any affect on x86 but may possibly
have an affect for the powerpc platform (try enabling DMA for powerpc by
setting IVTV_USE_PIO 0 in ivtv-driver.h and see if this fixes DMA on that
platform).
Tim
--- Tim Harvey <[EMAIL PROTECTED]> wrote:
> Sorry, somehow I didn't get CONFIG_VIDEO_CX25840 defined - once I did that I
> see the cx25840 fine. I'm still having issues with DMA and unlike ivtv-0.8.2
> I'm now also having issues with PIO.
>
> Looks like there has been a lot of changes since 0.8.2. I notice that there
> is now read_enc/write_enc and read_dec/write_dec functions for accessing data
> from the enc/dec buffers directly. At first glance I figured I should make
> these endian-safe but that fixed some issues and caused others so instead I
> just fixed the endienness issues around DMA_MAGIC_COOKIE.
>
> With that in place and using PIO I never get the IVTV_IRQ_ENC_DMA_COMPLETE
> interrupts that I would get with ivtv-0.8.2 PIO (Note I'm using ivtv_debug=75
> and have added the pid to the debug print to show the thread):
>
> # dd if=/dev/video0 of=/mnt/tmp/test_capture.mpg bs=1024 count=512
> [807] ivtv0 info: ivtv start v4l2 stream
> [807] ivtv0 info: Setup VBI API header 0x0000bd03 pkts 1 buffs 4 ln 24 sz
> 1456
> [807] ivtv0 info: Setup VBI start 0x002fea04 frames 4 fpi 1 lines 0x00000140
> [807] ivtv0 info: ENC: PGM Index at 0x00180150 with 400 elements
> [0] ivtv0 irq: ENC START CAP 0: 000dd700 00007fc0
> [0] ivtv0 dma: PIO encoder MPEG: 0x00007fc0 bytes at 0x000dd700
> [0] ivtv0 dma: PIO encoder MPEG completed (dd700)
> [807] ivtv0 info: ENC: read(1024), got 1024
> [807] ivtv0 info: ENC: read(1024), got 1024
> [807] ivtv0 info: ENC: read(1024), got 1024
> ....
>
> eventually the enc thread ([807]) stalls when it runs out of data. I never
> see an IVTV_IRQ_ENC_DMA_COMPLETE to queue up more data.
>
> For DMA:
> # dd if=/dev/video0 of=/mnt/tmp/test_capture.mpg bs=1024 count=512
> [807] ivtv0 info: ivtv start v4l2 stream
> [807] ivtv0 info: Setup VBI API header 0x0000bd03 pkts 1 buffs 4 ln 24 sz
> 1456
> [807] ivtv0 info: Setup VBI start 0x002fea04 frames 4 fpi 1 lines 0x00000140
> [807] ivtv0 info: ENC: PGM Index at 0x00180150 with 400 elements
> [0] ivtv0 irq: ENC START CAP 0: 000dd700 00008fc0
> [0] ivtv0 dma: DMA encoder MPEG: 0x00008fc0 bytes at 0x000dd700
> [0] ivtv0 dma: start DMA for encoder MPEG
> (hangs at this point)
>
> Here is my IVTV init:
>
> Linux video capture interface: v2.00
> ivtv: ==================== START INIT IVTV ====================
> ivtv: version 0.10.0 (development revision 3718M) loading
> ivtv: Linux version: 2.6.19 mod_unload ARMv5
> ivtv: In case of problems please include the debug info between
> ivtv: the START INIT IVTV and END INIT IVTV lines, along with
> ivtv: any module options, when mailing the ivtv-users mailinglist.
> ivtv0: Autodetected Yuan MPC622 card (cx23416 based)
> [766] ivtv0 info: base addr: 0x48000000
> [766] ivtv0 info: Enabling pci device
> PCI: enabling device 0000:00:02.0 (0140 -> 0142)
> [766] ivtv0 info: Attempting to enable Bus Mastering
> [766] ivtv0 info: Bus Mastering Enabled.
> ivtv0: Unreasonably low latency timer, setting to 64 (was 0)
> [766] ivtv0 info: 22 (rev 1) at 00:02.0, irq: 27, latency: 64, memory:
> 0x48000000
> [766] ivtv0 info: attempting ioremap at 0x48000000 len 0x00800000
> [766] ivtv0 info: attempting ioremap at 0x4a000000 len 0x00010000
> [766] ivtv0 info: Preparing for firmware halt.
> [766] ivtv0 info: Stopping VDM
> [766] ivtv0 info: Stopping AO
> [766] ivtv0 info: pinging (?) APU
> [766] ivtv0 info: Stopping VPU
> [766] ivtv0 info: Resetting Hw Blocks
> [766] ivtv0 info: Stopping SPU
> [766] ivtv0 info: init Encoder SDRAM pre-charge
> [766] ivtv0 info: init Encoder SDRAM refresh to 1us
> [766] ivtv0 info: Sleeping for 600ms (600 recommended)
> [766] ivtv0 info: Loading encoder image
> ivtv0: loaded v4l-cx2341x-enc.fw firmware (262144 bytes)
> [766] ivtv0 info: Getting firmware version..
> ivtv0: Encoder revision: 0x02050032
> [766] ivtv0 info: GPIO initial dir: 0000c000 out: 00000000
> [766] ivtv0 info: activating i2c...
> [766] ivtv0 info: Active card count: 1.
> tuner 0-004b: chip found @ 0x96 (ivtv i2c driver #0)
> [766] ivtv0 info: Loaded module tuner
> cx25840 0-0044: cx25843-23 found @ 0x88 (ivtv i2c driver #0)
> cx25840 0-0044: loaded v4l-cx25840.fw firmware (16382 bytes)
> [766] ivtv0 info: Loaded module cx25840
> ivtv0: Registered device video0 for encoder MPEG (4 MB)
> [766] ivtv0 info: Allocate DMA encoder MPEG stream: 128 x 32768 buffers
> (4096kB total)
> ivtv0: Registered device video32 for encoder YUV (2 MB)
> [766] ivtv0 info: Allocate DMA encoder YUV stream: 194 x 10800 buffers
> (2046kB total)
> ivtv0: Registered device vbi0 for encoder VBI (1 MB)
> [766] ivtv0 info: Allocate DMA encoder VBI stream: 60 x 17472 buffers (1023kB
> total)
> ivtv0: Registered device video24 for encoder PCM audio (1 MB)
> [766] ivtv0 info: Allocate DMA encoder PCM audio stream: 227 x 4608 buffers
> (1021kB total)
> [766] ivtv0 info: Starting Threads
> [766] ivtv0 irq: Masking interrupts
> tuner 0-004b: setting tuner address to 61
> tuner 0-004b: type set to tda8290+75a
> [766] ivtv0 info: Changing input from 1 to 0
> [766] ivtv0 info: Mute
> [766] ivtv0 info: Unmute
> [766] ivtv0 info: Switching standard to 1000.
> [766] ivtv0 info: Mute
> [766] ivtv0 info: v4l2 ioctl: set frequency 1076
> [766] ivtv0 info: Unmute
> ivtv0: Initialized Yuan MPC622, card #0
> ivtv: ==================== END INIT IVTV ====================
>
> So it would seem that in both PIO and DMA cases my issue is that I'm not
> continuing to get interrupts after the IVTV_IRQ_ENC_START_CAP interrupt.
>
> Tim
>
> >
> >
> >----- Original Message ----
> >From: Tim Harvey <[EMAIL PROTECTED]>
> >To: Discussion list for development of the IVTV driver
> <[email protected]>
> >Sent: Wednesday, January 17, 2007 4:31:34 PM
> >Subject: Re: [ivtv-devel] ivtv on ARM
> >
> >Fair enough - I've updated to 2.6.19 and ivtv-svn. With ivtv-svn however,
> I'm not getting as far as I was because the cx25840 is not being detected on
> the i2c bus (however the tda8290 tuner is being detected on the same bus).
> I've tried both newi2c=0 and 1.
> >
> >I had this same situation occur on a board with a 266MHz cpu with the 0.8.2
> code so I'm guessing its timing related. I guess I'll have to add some
> debugging to the i2c layer?
> >
> >Tim
> >
> >
> >----- Original Message ----
> >From: Hans Verkuil <[EMAIL PROTECTED]>
> >To: Tim Harvey <[EMAIL PROTECTED]>; Discussion list for development of
> the IVTV driver <[email protected]>
> >Sent: Wednesday, January 17, 2007 1:14:18 PM
> >Subject: Re: [ivtv-devel] ivtv on ARM
> >
> >Hi Tim,
> >
> >Sorry for not answering your original mail, I'll try to do so in this
> >mail.
> >
> >On Wednesday 17 January 2007 21:37, Tim Harvey wrote:
> >> >Greetings,
> >> >
> >> >has anyone ever successfully run ivtv on an ARM processor? I'm
> >> > running linux 2.6.18.6 on an IXP425 xscale CPU and a YUAN MPC622
> >> > card (cx23416) and am having issues with DMA. I'm not sure the
> >> > arm-linux architecture supports the scatter-gather DMA being used.
> >> > I've tried to force using PIO via #define IVTV_ENC_PIO 1 but that
> >> > seems to fail as well.
> >
> >The pci_map_sg etc. dma scatter gather functions from the kernel are
> >only used by the PVR350 (cx23415-based), not be a cx23416-based card.
> >So this shouldn't be a problem. I see no reason why it would fail to
> >work, except for endianness problems.
> >
> >> >
> >> >Before I post a question to the arm-linux list any suggestions or
> >> > explanations of what ivtv is using for DMA (looks like
> >> > scatter-gather dma list?).
> >
> >All known documentation of the cx23415/6 is in the
> >Documentation/video4linux/cx2341x directory of the linux kernel
> >(starting from 2.6.18). Including how the DMA is programmed.
> >
> >BTW: I recommend that you use the ivtv-trunk as the basis for your ARM
> >port. It will replace the current ivtv sources for 2.6.18 and 2.6.19
> >when done. I hope to finish a few minor issues this weekend and make
> >release candidates available for testing, so it should be a solid base
> >to work from. Note that the current trunk requires a 2.6.19 kernel.
> >
> >One very good reason for using the trunk is that the DMA code is much
> >more centralized (almost everything is in ivtv-irq.c). That should make
> >it much easier for you to fix the endianness issues.
> >
> >> I've determined from the source that ivtv is not big-endian safe but
> >> after fixing a couple of obvious endian issues regarding (looking at
> >> the buffer to ensure it starts with 0x0000001fe in
> >> ivtv_FROM_DMA_done) I'm able to get it to run on my ARM big-endian
> >> platform using PIO, but not DMA.
> >>
> >> Here are some follow-up questions for the list:
> >>
> >> - any areas I should be looking at for endianess issues? I believe
> >> readl/writel should be byteswapped for arm-linux so register
> >> read/writes should be ok, correct?
> >
> >Doesn't readl/writel already byteswap for ARM?
> >
> >> - I've only been able to get the driver to work using PIO
> >> (IVTV_USE_PIO=1) - when I use DMA the DMA transfer never appears to
> >> start and I get the following errors: ivtv0 warning: ENC: REG_DMAXFER
> >> 2 wait failed
> >> ivtv0 warning: ENC: (0) DMA Error 0x00000001 00000001
> >> ivtv0 warning: ENC: REG_DMAXFER 2 wait failed
> >> ivtv0 warning: ENC: (1) DMA Error 0x00000001 00000001
> >> ivtv0 warning: ENC: REG_DMAXFER 2 wait failed
> >> ivtv0 warning: ENC: (2) DMA Error 0x00000001 00000001
> >> ivtv0 warning: ENC: REG_DMAXFER 2 wait failed
> >> ivtv0 warning: ENC: (3) DMA Error 0x00000001 00000001
> >> ivtv0 warning: ENC: REDO DMA took too many tries.
> >> ivtv0 warning: Error Encoder DMA
> >
> >Again, use the trunk code. Error reporting is much better there. I
> >recommend to either load ivtv with ivtv_debug=79 or run 'ivtvctl -D79'
> >to turn on the most relevant debugging for interrupt and DMA handling.
> >
> >> - using PIO I occasionally get interrupts for IVTV_IRQ_DEC_DMA_2 and
> >> IVTV_IRQ_DEC_DMA_0 (bit 0 and bit 2). It appears that these may only
> >> come when I'm loading the system heavily with debugging output - what
> >> do these mean?
> >
> >Again, move to the trunk code.
> >
> >> - is there a software development manual anywhere for the cx23416
> >> which details its registers?
> >
> >As mentioned above, it's in the kernel documentation directory.
> >
> >> - there is a DYNAMIC_MEMORY_ALLOC defined in ivtv-driver.h for
> >> __powerpc__ but its not used anywhere. I see the point in needing it
> >> for an embedded platform and I assume the thought was that instead of
> >> the driver allocating DMA buffers on init it would allocate them when
> >> needed (ie, no need to have YUV buffers if your not using YUV mode) -
> >> was any work ever done on this?
> >
> >No, dynamic allocation gave more problems than it solved. It's
> >completely dropped in the trunk code.
> >
> >Basically the moral of my email is that you should use the trunk code.
> >If it is a problem for you to also update to the 2.6.19 kernel
> >(recommend 2.6.19.2 or up), then you can also wait until this weekend.
> >I want to release trunk-based beta versions for 2.6.18 as well.
> >
> >Regards,
> >
> > Hans
> >
> >
> >
> >
> >_______________________________________________
> >ivtv-devel mailing list
> >[email protected]
> >http://ivtvdriver.org/mailman/listinfo/ivtv-devel
> >
>
>
>
> _______________________________________________
> ivtv-devel mailing list
> [email protected]
> http://ivtvdriver.org/mailman/listinfo/ivtv-devel
>
Index: ivtv-irq.c
===================================================================
--- ivtv-irq.c (revision 3742)
+++ ivtv-irq.c (working copy)
@@ -331,7 +331,7 @@
/* Sync Hardware SG List of buffers */
pci_dma_sync_single_for_device((struct pci_dev *)itv->dev,
- s->SG_handle, sizeof(struct ivtv_SG_element) * s->buffers, s->dma);
+ s->SG_handle, sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE);
if (lock)
spin_lock_irqsave(&itv->dma_reg_lock, flags);
if (!test_bit(IVTV_F_I_DMA, &itv->i_flags)) {
@@ -382,7 +382,7 @@
/* Sync Hardware SG List of buffers */
pci_dma_sync_single_for_device((struct pci_dev *)itv->dev,
- s->SG_handle, sizeof(struct ivtv_SG_element) * s->buffers, s->dma);
+ s->SG_handle, sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE);
write_reg(s->SG_handle, IVTV_REG_ENCDMAADDR);
write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER);
set_bit(IVTV_F_I_DMA, &itv->i_flags);
@@ -422,7 +422,7 @@
IVTV_DEBUG_DMA("DEC DATA READ %s: %d\n", s->name, s->q_dma.bytesused);
pci_dma_sync_single_for_cpu((struct pci_dev *)itv->dev,
- s->SG_handle, sizeof(struct ivtv_SG_element) * s->SG_length, s->dma);
+ s->SG_handle, sizeof(struct ivtv_SG_element) * s->SG_length, PCI_DMA_TODEVICE);
/* For some reason must kick the firmware, like PIO mode,
I think this tells the firmware we are done and the size
@@ -468,7 +468,7 @@
itv->cur_dma_stream = -1;
dma_post(s);
pci_dma_sync_single_for_cpu((struct pci_dev *)itv->dev,
- s->SG_handle, sizeof(struct ivtv_SG_element) * s->buffers, s->dma);
+ s->SG_handle, sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE);
if (test_and_clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags)) {
s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
dma_post(s);
Index: ivtv-queue.c
===================================================================
--- ivtv-queue.c (revision 3742)
+++ ivtv-queue.c (working copy)
@@ -232,6 +232,7 @@
}
s->SG_length = 0;
s->SG_handle = pci_map_single(itv->dev, s->SGarray, SGsize, s->dma);
+ pci_dma_sync_single_for_cpu(itv->dev, s->SG_handle, SGsize, PCI_DMA_TODEVICE);
}
/* allocate stream buffers. Initially all buffers are in q_free. */
@@ -246,9 +247,11 @@
break;
}
INIT_LIST_HEAD(&buf->list);
- if (s->dma != PCI_DMA_NONE)
+ if (s->dma != PCI_DMA_NONE) {
buf->dma_handle = pci_map_single(s->itv->dev,
buf->buf, s->buf_size + 256, s->dma);
+ ivtv_buf_sync_for_cpu(s, buf);
+ }
ivtv_enqueue(s, buf, &s->q_free);
}
if (i == s->buffers)
Index: ivtv-udma.c
===================================================================
--- ivtv-udma.c (revision 3742)
+++ ivtv-udma.c (working copy)
@@ -79,6 +79,8 @@
/* Map DMA Page Array Buffer */
itv->udma.SG_handle = pci_map_single(itv->dev, itv->udma.SGarray,
sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE);
+ pci_dma_sync_single_for_cpu(itv->dev, itv->udma.SG_handle,
+ sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE);
}
}
_______________________________________________
ivtv-devel mailing list
[email protected]
http://ivtvdriver.org/mailman/listinfo/ivtv-devel