[PATCH v4 4/4] media: pxa_camera: conversion to dmaengine
Convert pxa_camera to dmaengine. This removes all DMA registers manipulation in favor of the more generic dmaengine API. The functional level should be the same as before. The biggest change is in the videobuf_sg_splice() function, which splits a videobuf-dma into several scatterlists for 3 planes captures (Y, U, V). Signed-off-by: Robert Jarzmik --- Since v1: Guennadi's fixes dma tasklet functions prototypes change (trivial move) Since v2: sglist cut revamped with Guennadi's comments Since v3: sglist split removed after Andrew's merge in -mm tree in lib/ taken into account Vinod's change to DMA_CTRL_REUSE --- drivers/media/platform/soc_camera/Kconfig | 1 + drivers/media/platform/soc_camera/pxa_camera.c | 404 +++-- 2 files changed, 172 insertions(+), 233 deletions(-) diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig index f2776cd415ca..e5e2d6cf6638 100644 --- a/drivers/media/platform/soc_camera/Kconfig +++ b/drivers/media/platform/soc_camera/Kconfig @@ -30,6 +30,7 @@ config VIDEO_PXA27x tristate "PXA27x Quick Capture Interface driver" depends on VIDEO_DEV && PXA27x && SOC_CAMERA select VIDEOBUF_DMA_SG + select SG_SPLIT ---help--- This is a v4l2 driver for the PXA27x Quick Capture Interface diff --git a/drivers/media/platform/soc_camera/pxa_camera.c b/drivers/media/platform/soc_camera/pxa_camera.c index cdfb93aaee43..969140634f3d 100644 --- a/drivers/media/platform/soc_camera/pxa_camera.c +++ b/drivers/media/platform/soc_camera/pxa_camera.c @@ -28,6 +28,9 @@ #include #include #include +#include +#include +#include #include #include @@ -38,7 +41,6 @@ #include -#include #include #define PXA_CAM_VERSION "0.0.6" @@ -175,21 +177,16 @@ enum pxa_camera_active_dma { DMA_V = 0x4, }; -/* descriptor needed for the PXA DMA engine */ -struct pxa_cam_dma { - dma_addr_t sg_dma; - struct pxa_dma_desc *sg_cpu; - size_t sg_size; - int sglen; -}; - /* buffer for one video frame */ struct pxa_buffer { /* common v4l buffer stuff -- must be first */ struct videobuf_buffer vb; u32 code; /* our descriptor lists for Y, U and V channels */ - struct pxa_cam_dma dmas[3]; + struct dma_async_tx_descriptor *descs[3]; + dma_cookie_tcookie[3]; + struct scatterlist *sg[3]; + int sg_len[3]; int inwork; enum pxa_camera_active_dma active_dma; }; @@ -207,7 +204,7 @@ struct pxa_camera_dev { void __iomem*base; int channels; - unsigned intdma_chans[3]; + struct dma_chan *dma_chans[3]; struct pxacamera_platform_data *pdata; struct resource *res; @@ -222,7 +219,6 @@ struct pxa_camera_dev { spinlock_t lock; struct pxa_buffer *active; - struct pxa_dma_desc *sg_tail[3]; struct tasklet_struct task_eof; u32 save_cicr[5]; @@ -259,7 +255,6 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) { struct soc_camera_device *icd = vq->priv_data; - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct videobuf_dmabuf *dma = videobuf_to_dma(>vb); int i; @@ -276,61 +271,40 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) if (buf->vb.state == VIDEOBUF_NEEDS_INIT) return; - for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) { - if (buf->dmas[i].sg_cpu) - dma_free_coherent(ici->v4l2_dev.dev, - buf->dmas[i].sg_size, - buf->dmas[i].sg_cpu, - buf->dmas[i].sg_dma); - buf->dmas[i].sg_cpu = NULL; + for (i = 0; i < 3 && buf->descs[i]; i++) { + dmaengine_desc_free(buf->descs[i]); + kfree(buf->sg[i]); + buf->descs[i] = NULL; + buf->sg[i] = NULL; + buf->sg_len[i] = 0; } videobuf_dma_unmap(vq->dev, dma); videobuf_dma_free(dma); buf->vb.state = VIDEOBUF_NEEDS_INIT; -} - -static int calculate_dma_sglen(struct scatterlist *sglist, int sglen, - int sg_first_ofs, int size) -{ - int i, offset, dma_len, xfer_len; - struct scatterlist *sg; - - offset = sg_first_ofs; - for_each_sg(sglist, sg, sglen, i) { - dma_len = sg_dma_len(sg); - - /* PXA27x Developer's Manual
[PATCH v4 4/4] media: pxa_camera: conversion to dmaengine
Convert pxa_camera to dmaengine. This removes all DMA registers manipulation in favor of the more generic dmaengine API. The functional level should be the same as before. The biggest change is in the videobuf_sg_splice() function, which splits a videobuf-dma into several scatterlists for 3 planes captures (Y, U, V). Signed-off-by: Robert Jarzmik robert.jarz...@free.fr --- Since v1: Guennadi's fixes dma tasklet functions prototypes change (trivial move) Since v2: sglist cut revamped with Guennadi's comments Since v3: sglist split removed after Andrew's merge in -mm tree in lib/ taken into account Vinod's change to DMA_CTRL_REUSE --- drivers/media/platform/soc_camera/Kconfig | 1 + drivers/media/platform/soc_camera/pxa_camera.c | 404 +++-- 2 files changed, 172 insertions(+), 233 deletions(-) diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig index f2776cd415ca..e5e2d6cf6638 100644 --- a/drivers/media/platform/soc_camera/Kconfig +++ b/drivers/media/platform/soc_camera/Kconfig @@ -30,6 +30,7 @@ config VIDEO_PXA27x tristate PXA27x Quick Capture Interface driver depends on VIDEO_DEV PXA27x SOC_CAMERA select VIDEOBUF_DMA_SG + select SG_SPLIT ---help--- This is a v4l2 driver for the PXA27x Quick Capture Interface diff --git a/drivers/media/platform/soc_camera/pxa_camera.c b/drivers/media/platform/soc_camera/pxa_camera.c index cdfb93aaee43..969140634f3d 100644 --- a/drivers/media/platform/soc_camera/pxa_camera.c +++ b/drivers/media/platform/soc_camera/pxa_camera.c @@ -28,6 +28,9 @@ #include linux/clk.h #include linux/sched.h #include linux/slab.h +#include linux/dmaengine.h +#include linux/dma-mapping.h +#include linux/dma/pxa-dma.h #include media/v4l2-common.h #include media/v4l2-dev.h @@ -38,7 +41,6 @@ #include linux/videodev2.h -#include mach/dma.h #include linux/platform_data/camera-pxa.h #define PXA_CAM_VERSION 0.0.6 @@ -175,21 +177,16 @@ enum pxa_camera_active_dma { DMA_V = 0x4, }; -/* descriptor needed for the PXA DMA engine */ -struct pxa_cam_dma { - dma_addr_t sg_dma; - struct pxa_dma_desc *sg_cpu; - size_t sg_size; - int sglen; -}; - /* buffer for one video frame */ struct pxa_buffer { /* common v4l buffer stuff -- must be first */ struct videobuf_buffer vb; u32 code; /* our descriptor lists for Y, U and V channels */ - struct pxa_cam_dma dmas[3]; + struct dma_async_tx_descriptor *descs[3]; + dma_cookie_tcookie[3]; + struct scatterlist *sg[3]; + int sg_len[3]; int inwork; enum pxa_camera_active_dma active_dma; }; @@ -207,7 +204,7 @@ struct pxa_camera_dev { void __iomem*base; int channels; - unsigned intdma_chans[3]; + struct dma_chan *dma_chans[3]; struct pxacamera_platform_data *pdata; struct resource *res; @@ -222,7 +219,6 @@ struct pxa_camera_dev { spinlock_t lock; struct pxa_buffer *active; - struct pxa_dma_desc *sg_tail[3]; struct tasklet_struct task_eof; u32 save_cicr[5]; @@ -259,7 +255,6 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) { struct soc_camera_device *icd = vq-priv_data; - struct soc_camera_host *ici = to_soc_camera_host(icd-parent); struct videobuf_dmabuf *dma = videobuf_to_dma(buf-vb); int i; @@ -276,61 +271,40 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) if (buf-vb.state == VIDEOBUF_NEEDS_INIT) return; - for (i = 0; i ARRAY_SIZE(buf-dmas); i++) { - if (buf-dmas[i].sg_cpu) - dma_free_coherent(ici-v4l2_dev.dev, - buf-dmas[i].sg_size, - buf-dmas[i].sg_cpu, - buf-dmas[i].sg_dma); - buf-dmas[i].sg_cpu = NULL; + for (i = 0; i 3 buf-descs[i]; i++) { + dmaengine_desc_free(buf-descs[i]); + kfree(buf-sg[i]); + buf-descs[i] = NULL; + buf-sg[i] = NULL; + buf-sg_len[i] = 0; } videobuf_dma_unmap(vq-dev, dma); videobuf_dma_free(dma); buf-vb.state = VIDEOBUF_NEEDS_INIT; -} - -static int calculate_dma_sglen(struct scatterlist *sglist, int sglen, - int sg_first_ofs, int size) -{ - int i, offset, dma_len, xfer_len; - struct scatterlist